对于那些不熟悉的人,代理继承如下所示:
var Surrogate = function () {}
var extend = function (Base, Sub) {
Surrogate.prototype = Base.prototype;
Sub.prototype = new Surrogate();
Sub.prototype.constructor = Sub;
}
var Animal = function (name) {
this.name = name;
};
Animal.prototype.speak = function () {
return this.getSound() + ' ' + this.name;
};
Animal.prototype.getSound = function () {
// Abstract
};
var Cat = function (name) {
Animal.call(this, name);
};
extend(Animal, Cat);
Cat.prototype.getSound = function () {
return 'Meow';
};
var kitty = new Cat('Maru');
console.log(kitty.speak()); // Logs "Meow Maru"
console.log(kitty instanceof Animal); // Logs true
console.log(kitty instanceof Cat); // Logs true
console.log(kitty.constructor == Cat); // Logs true
基本上要创建一个继承自 的构造函数Animal
,我们创建另一个构造函数(在本例中为),使用 的正确值Cat
调用构造函数,然后使用该函数将的原型设置为没有名称属性。认为 using与except 相同是未定义的。Animal
this
extend
Cat
Animal
extend(Animal, Cat)
Cat.prototype = new Animal()
Cat.prototype.name
以上工作完美,我有一个关于它的附带问题稍后。
我想把它提升到一个新的水平并隐藏Surrogate
在一个闭包中,所以我改变了 and 的声明,Surrogate
看起来extend
像这样:
var extend = (function () {
var Surrogate = function () {};
return function (Base, Sub) {
Surrogate.prototype = Base.prototype;
Sub.prototype = new Surrogate();
Sub.prototype.constructor = Sub;
};
});
现在,当我运行脚本时,它在第一个日志语句中失败:
TypeError: Object [object Object] has no method 'speak'
extend.js
但是,使用以下内容创建另一个文件:
var Surrogate = function () {};
module.exports = function (Base, Sub) {
Surrogate.prototype = Base.prototype;
Sub.prototype = new Surrogate();
Sub.prototype.constructor = Sub;
}
extend
并将主脚本中的声明更改为var extend = require('./extend');
有效,并且Surrogate
按预期隐藏。
对于主要问题:据我所知,node 和其他 CommonJS 系统只是将模块包装在一个闭包函数中,就像我最初尝试做的那样。为什么模块版本有效,但我的闭包版本无效?
对于上面提到的附带问题:我很惊讶Sub.prototype.constructor = Sub
。我认为应该是这样,Sub.prototype.constructor = Base
但这会导致最后一个日志记录语句记录false
。我想我已经为自己回答了这个问题,但我认为这constructor
是构造对象的属性,而不是原型。是不是反过来?
更新
我刚刚使用 AMD 使用了一个名为extend
如下定义的模块进行了尝试:
define(function () {
var Surrogate = function () {};
return function (Base, Sub) {
Surrogate.prototype = Base.prototype;
Sub.prototype = new Surrogate();
Sub.prototype.constructor = Sub;
};
});
它工作得很好。我觉得我在这里忽略了一些非常简单的东西……为什么这在模块系统中可以正常工作,但在普通闭包中却不行?我已经在 node.js、Chrome 和 Firefox 中测试了所有版本(普通、闭包和模块)。