0

我有这个代码:

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 的副本,我可以在其中添加/覆盖属性。这个对吗?

4

3 回答 3

3

在这里调用如何使我的初级Stickman拥有Stickman的所有方法

您在代码中的注释似乎表明您在Stickman构造函数中设置所有属性(也是方法)。因此,如果您调用Stickman并显式设置this为新JuniorStickman实例 ( ),则分配给内部的Stickman.call(this);所有属性都将分配给新实例。thisStickman

.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);
于 2013-04-01T23:56:16.833 回答
0

JavaScript 原型就像子类。但是“子”对象的所有实例都继承了一个父实例。更改的复杂值会针对所有子实例进行更改。

当使用 parent.call(thisContext) 时,使用 this.somevar 在父函数体中声明的父变量将对子实例变得唯一,因为它们被初始化为子的 this 上下文。当你只有 parent.call(this 那么孩子不会是父母的一个实例,所以:

(child instanceof parent) 如果您只使用 parent.call(this

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
于 2013-04-02T00:15:42.870 回答
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() 的时间戳都是相同的,但是如果您取消注释该行,那么它们的行为将与您希望的一样。

于 2013-04-01T23:58:10.263 回答