我有这段代码:
function Stickman() {
//some methods and properties
}
function JuniorStickman() {
Stickman.call(this);
this.p = new value // override a property in Stickman
}
JuniorStickman.prototype = new Stickman();
junior = new JuniorStickman();
我在MDN的示例中调整了此代码:https://developer.mozilla.org/en-US/docs/JavaScript/Introduction_to_Object-Oriented_JavaScript
我不明白的是:call()和行
JuniorStickman.prototype = new Stickman()
似乎做同样的事情。如果我注释掉这行
JuniorStickman.prototype = new Stickman();
我的JuniorStickman仍然拥有Stickman的所有方法和属性;真正;他的原型属性现在是JuniorStickman而不是Stickman,但似乎并不重要。
呼叫如何在这里使我的Junior Stickman(初级)拥有Stickman的所有方法并且是必要的原型分配?
据我所知,call()并没有真正给我继承。我只是得到一种Stickman的副本,我可以添加/覆盖属性。它是否正确?
答案 0 :(得分:3)
呼叫如何在这里使我的juniorStickman拥有Stickman的所有方法
您在代码中的注释似乎表明您在Stickman
构造函数中设置了所有属性(也包括方法)。因此,如果您致电Stickman
并明确将this
设置为新的JuniorStickman
实例(Stickman.call(this);
),则this
内的Stickman
所有属性被分配给新实例。
.call
[MDN]所做的就是在函数内部设置this
来引用第一个参数。例如:
function foo() {
alert(this.bar);
}
foo.call({bar: 42}); // alerts 42
foo.call({bar: 'baz'}); // alerts baz
为什么 在这里使用.call
?它与在其他语言中调用super()
扮演的角色相同:它在新的子实例上执行父构造函数。
是必要的原型分配
不是你的情况。但通常您将应该跨实例共享的所有属性分配给函数的原型,即Stickman.prototype
。例如,通常将方法分配给原型。只应在构造函数中为每个实例分配特定的属性。
如果您不进行此分配,JuniorStickman
的实例将不会分配给Stickman.prototype
的任何方法,因为它不在实例的原型链中。
FWIW,通过为原型分配父实例来设置继承并不是最佳方式。如果Stickman
需要强制性参数,该怎么办?你会通过哪些?
此时您不想创建新的Stickman
实例,只需将Stickman.prototype
带入原型链即可。这可以使用Object.create
[MDN]:
JuniorStickman.prototype = Object.create(Stickman.prototype);
答案 1 :(得分:0)
如果您的Stickman()构造函数为每个新实例执行不同的操作(假设它将属性设置为等于创建它的时间),那么您希望JuniorStickman()的每个实例都调用Stickman()构造函数而不是依赖于当你调用Stickman()来设置原型时将存储在原型中的时间戳。
例如:
function a() {
this.time = new Date().getTime();
}
function b() {
// a.call(this)
this.hello = "something";
}
b.prototype = new a();
随着该行被注释掉,每个新b()的时间戳都是相同的,但是如果你取消注释该行,那么它们的行为就像你希望的那样。
答案 2 :(得分:0)
JavaScript原型就像子类。但是“子”对象的所有实例都继承了一个父实例。将更改所有子实例的复杂值。
当使用parent.call(thisContext)时,在父的函数体中使用this.somevar声明的父变量将变为子实例的唯一,因为它们被初始化为子的此上下文。 当你只有parent.call时(那么孩子就不会是父的实例所以:
如果你只使用parent.call(),那么(child instanceof parent)将为false
function parent(){
this.arr=[];
this.name="parent";
}
function child1(){
parent.call(this);//sets all this elements
//of parent to the current
// instance of child1
}
child1.prototype = new parent();
function child2(){
}
child2.prototype = new parent();
var c1=new child1();
c1.name="c1"
c1.arr.push(["c1"]);
var anotherc1=new child1();
anotherc1.name="another c1";
anotherc1.arr.push("another c1");
var c2 = new child2();
c2.name="c2";
c2.arr.push(["c2"]);
var anotherc2 = new child2();
anotherc2.name="another c2";
anotherc2.arr.push(["another c2"]);
console.log(c1.name,c1.arr);//["c1"]
console.log(anotherc1.name,anotherc1.arr);//["anotherc1"]
console.log(c2.name,c2.arr);//["c2","anotherc2"]
console.log(anotherc2.name,anotherc2.arr);//["c2","anotherc2"]
console.log(c1 instanceof parent);//true