OO Javascript:使用原型和调用

时间:2013-04-01 23:51:12

标签: javascript oop call prototype

我有这段代码:

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的副本,我可以添加/覆盖属性。它是否正确?

3 个答案:

答案 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