在一些大型项目中看到了这种JavaScript模式,它将ClassA的属性“复制”或“实现”到ClassB,但无法弄清楚使用“.call()”在ClassB的构造函数中调用ClassA的空构造函数的目的是什么。将ClassB实例作为“this”绑定传递?
var ClassA = function() {
//this function is totally empty
};
ClassA.prototype = {
jump: function() {...some code...},
dance: function() {
if (this.canDance) {
alert("dance");
}
}
};
ClassA.implementOn = function(targetClassOrObject) {
for ( var prop in ClassA.prototype ) {
targetClassOrObject[ prop ] = ClassA.prototype[ prop ];
}
};
var ClassB = function() {
this.canDance = true;
ClassA.call(this); // <------------What's the purpose of this line?
};
ClassA.implementOn(ClassB.prototype);
var instanceOfB = new ClassB();
instanceOfB.dance();
答案 0 :(得分:2)
如果ClassA
构造函数为空,那么这里没有什么大惊喜 - call
ClassA
的空构造函数绝对没有。
当您决定希望ClassA
的构造函数非空时,您会看到该行现在具有非常重要的作用:构造ClassB
对象也会调用{ {1}} - 新构造的ClassA
对象上下文中的特定构造函数行为,如果ClassB
是ClassB
的逻辑“子类”,那么这是您所期望的。
(当然,JavaScript没有正确的“子类”,但这显然是尝试在语言中实现基于类的行为。)
答案 1 :(得分:1)
使用“.call()”在ClassB的构造函数中调用ClassA的空构造函数的目的
当ClassA
不为空时,让脚本仍然有效。当然,目前它什么都不做,但未来可能会有所改变。因此,最好实现完整的继承模式,以便以后更容易更改代码而不会引入错误。
一旦ClassA
更改以实现自定义的特定于实例的属性(在构造函数中设置),您也希望将它们放在ClassB
个实例上。因此,您在初始化期间也会在ClassA
个实例上调用ClassB
构造函数。
答案 2 :(得分:1)
如果ClassA
构造函数为空(如示例代码中所示),那么是的,它什么都不做。
你看到这种模式的原因是它没有的时候。它类似于基于类的OO语言中的super
调用。
如果你必须在ClassA
构造函数中做一些工作来获得一个处于正确状态的对象,那么你很可能想要做同样的工作a&#34;子类&#34;。仅仅复制原型的属性可能还不够。
答案 3 :(得分:0)
使用.call
,您可以将被调用方法中的this
值更改为您指定的参数。 ClassA.call(this)
使用ClassA
作为上下文调用ClassB
构造函数。这允许您在ClassB
方法中使用ClassA
的属性。这些方法都通过ClassB
复制到ClassA.implementOn
。
您会注意到(new ClassA()).dance()
什么都不做,但(new ClassB()).dance()
提醒"dance"
因为this.canDance
是真的。