对于那些不熟悉的人,代理继承如下所示:
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
),使用适当的{Animal
构造函数调用this
构造函数{1}},然后使用extend
函数将Cat
的原型设置为Animal
的“实例”,而不使用name属性。考虑使用extend(Animal, Cat)
与Cat.prototype = new Animal()
相同,但Cat.prototype.name
未定义。
上述情况完美无缺,我稍后会对此提出质疑。
我希望将其提升到一个新级别,并将Surrogate
隐藏在闭包中,因此我将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
按预期隐藏。
对于主要问题:据我所知,节点和其他CommonJS系统只是将模块封装在一个闭包函数中,就像我最初尝试的那样。为什么模块版本可行,但我的带闭包的版本没有?
对于上面提到的附带问题:我对Sub.prototype.constructor = Sub
感到惊讶。我认为它应该是Sub.prototype.constructor = Base
,但这导致最后一个日志记录语句记录false
。我想我已经为自己回答了这个问题,但我认为constructor
是构造对象的属性,而不是原型。是相反吗?
更新
我刚刚使用名为extend
的模块对AMD进行了尝试,其定义如下:
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中的所有版本(普通版,闭包版和模块版)。
答案 0 :(得分:1)
var extend = (function () {
var Surrogate = function () {};
return function (Base, Sub) {
Surrogate.prototype = Base.prototype;
Sub.prototype = new Surrogate();
Sub.prototype.constructor = Sub;
};
});
应该是
var extend = (function () {
var Surrogate = function () {};
return function (Base, Sub) {
Surrogate.prototype = Base.prototype;
Sub.prototype = new Surrogate();
Sub.prototype.constructor = Sub;
};
})();
(我只是附加了()
来执行该功能。)
或者如果你想防止Surrogate可能被破坏的可能性(某些人可能会破坏它的构造函数 - 让它做一些事情):
var extend = function (Base, Sub) {
var Surrogate = function () {};
Surrogate.prototype = Base.prototype;
Sub.prototype = new Surrogate();
Sub.prototype.constructor = Sub;
};