-
-
Save allenfantasy/1e666aedf134938d7802 to your computer and use it in GitHub Desktop.
Implementation of inheritance in CoffeeScript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var __hasProp = {}.hasOwnProperty; | |
var __extends = function(child, parent) { | |
for (var key in parent) { | |
if (__hasProp.call(parent, key)) child[key] = parent[key]; | |
} | |
function ctor() { | |
// why set the prototype's constructor to child? | |
this.constructor = child; | |
} | |
ctor.prototype = parent.prototype; | |
child.prototype = new ctor(); | |
child.__super__ = parent.prototype; | |
return child; | |
}; |
回答自己之前提出来的问题:child 和 parent 都是构造函数,但函数本身也可能带有属性(类似于基于类的OOP语言中的class variable
),所以需要复制给子构造函数。
避免子构造函数通过 prototype 污染 Parent 对象的方法的关键在于 ctor
。请看例子:
function Person() {
this.age = 1;
this.name = "foo";
}
Person.prototype.greet = function() {
console.log("hello");
}
__extends(Student, Person);
function Student() {
return Student.__super__.constructor.apply(this, arguments);
}
Student.prototype.greet = function() {
console.log("hello, i am a student");
}
这段代码在最后尝试对 Student.prototype
进行修改,也就是我们所理解的重定义(override)。如果在 __extends
函数中不使用 ctor
作为过渡:
var __extends = function(child, parent) {
// 省略前面复制属性的代码...
child.prototype = parent.prototype; // 原来这里是用 ctor 的,现在不用了
child.__super__ = parent.prototype;
return child;
}
则会出现以下情况:
var p = new Person();
var s = new Student();
p.greet(); //=> hello, i am a student
s.greet(); //=> hello, i am a student
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
第5到7行的代码的意义是?在Coffeescript的源码中child和parent都是构造函数,所以不明白将构造函数的属性复制给子构造函数的用意在哪里。
这段代码可以让
通过Child函数创建的对象
继承Parent的原型
的所有属性,同时保证了不会对直接通过Parent创建的对象
造成污染。但如果需要
Child创建的对象
可以和Parent创建的对象
有一样的属性值的话,还需要在Child函数中显式的调用Parent函数(通过apply)。在Coffeescript中的实现如下: