通过互联网搜索我总是碰到这种Javascript类扩展方法
function extend(Child, Parent) {
var F = function() { }
F.prototype = Parent.prototype
Child.prototype = new F()
Child.prototype.constructor = Child
Child.superclass = Parent.prototype
}
但这与那个有什么不同?
function extend(Child, Parent) {
var p = new Parent()
Child.prototype = p
Child.prototype.constructor = Child
Child.superclass = p
}
这最后一个也很完美。那么我为什么要使用这个额外的var F = function() { }
移动呢?
答案 0 :(得分:7)
直接调用原始构造函数可能会产生不良副作用,如果未传递某些预期参数,则无法正常工作。
这就是他们使用“代理”功能的原因,它允许您获得一个继承自Parent()
的新对象,而不实际调用Parent()
。
这是一个简单的例子:
function Person(name, age) {
if (name === undefined)
throw "A name is required";
this.name = name + "";
this.age = age;
}
如果Person
是父项,那么它会抛出错误,因为没有传递name
。
答案 1 :(得分:1)
第一个例子是(作为评论中提到的cookie怪物)下面一段代码的垫片,可能更容易理解。:
function extend(Child, Parent) {
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
Child.superclass = Parent.prototype;
}
基本上,此实现使所有Child实例从(Child.prototype)继承的对象继承自所有Parent实例继承的对象(Parent.prototype)。直观地说,这是JavaScript提供的类继承的最准确表示。
extends的第二个实现是有缺陷的,因为所有Child实例都将从特定的Parent实例继承。如果父实例之间存在显着差异(例如,由于传递给构造函数的参数),Child实例无法准确表示,因为它们都是从通过调用不带参数的Parent构造函数创建的Parent实例继承的。
以下是第一个实现可以执行的操作,第二个实现不能执行的示例:
function Parent(name, age) {
this.name = name;
this.age = age;
}
Parent.prototype.greet = function() { return 'I am parent ' + this.name; }
function Child(name){
Parent.call(this, name, 20); // notice the call to the superclass
}
extend(Child, Parent);
Parent.prototype.greet = function() { return 'I am child ' + this.name + ' and i\'m ' + this.age; }
var c = new Child('Tom');
console.log(c.greet()); // I am child Tom and i'm 20
作为旁注,在Child构造函数中,我调用了Parent构造函数。在处理经典继承时,这实际上很常见,因此这是第一次实现的另一个要点。实际上并不需要,Child构造函数可以安全地忽略调用Parent构造函数,但请记住,该调用基本上确保在创建子实例之前创建的新对象是有效的Parent实例。在我的示例中,如果您不调用Parent构造函数,则不会在Child实例上设置name和age属性,因此greet方法将返回I am child undefined and i'm undefined
,远远超出您的预期。
答案 2 :(得分:0)
值得探索在JavaScript中扩展和向对象添加位的不同方法。
使用构造函数 (function(global){ 函数SuperClass(){}
var p = SuperClass.prototype;
p.doSomething = function() {
console.log('do something (super)')
};
function OtherClass() {
SuperClass.call(this);
}
OtherClass.prototype = new SuperClass();
Window.OtherClass = OtherClass;
}(window));
var o = new OtherClass();
使用object.create(无双重实例化) - 并非所有浏览器都支持。
(function (global) {
// SuperClass - superclass
function SuperClass() {
}
var p = SuperClass.prototype;
p.doSomething = function() {
console.log('do something (super)')
};
function OtherClass() {
SuperClass.call(this);
}
OtherClass.prototype = Object.create(SuperClass.prototype);
Window.OtherClass = OtherClass;
}(window));
功能性混合物: 当您想要将一组通用方法/属性混合到对象中时。
var mixin = function () {
this.methodA = function () {
};
this.methodA = function () {
};
return this;
}
var object = function () {
this.methodB = function () {
}
}
mixin.call(object.prototype);
所有方法的非常详细的解释:
http://javascriptweblog.wordpress.com/2011/05/31/a-fresh-look-at-javascript-mixins/