误解我有关于javascript原型的继承

时间:2010-12-22 05:32:36

标签: javascript inheritance

简单的问题。

    function p()
    {
        function A()
        {
            this.random = "random";
        }
        A.prototype.newfunc = function(){ alert("5");}

        function B()
        {

        }

        B.prototype = new A();

        var bObj = new B();
    }

Q1:当我设置B的原型时,我不知道B的原型属性将在何时/如果A的原型更新时更新。我的意思是,对我来说它只是继承/复制所有这些属性。它不像是:

B.prototype = A.prototype

其中B和A是同一个。

Q2:在A被返回并初始化为B的原型对象之后,JS如何知道不包含该原型属性?我的意思是,我们从来没有出现过这种情况,因为JS解释器只知道切断A原型的属性:

B.prototype = new A(); //any A object has an associated prototype object
    B.prototype.prototype;//after initialization we no longer have the separate prototype property of A

2 个答案:

答案 0 :(得分:2)

Q1:你自己说过 - 原型用于继承。因此B继承了A的所有属性。当您添加或更改A的成员时,B也会更改。正如你所说,它们不一样,但A是B的超类,如果超类中的任何内容发生变化,子类也会发生变化。但是,您可以将成员添加到B.prototype并在不更改A的​​情况下更改其行为。

试试这个:

    function A()
    {
    }

    A.prototype.alertname = function () 
    {
        alert (this.name);
    };

    function B()
    {
    }

    B.prototype = new A();

    var bObj = new B();
    var aObj = new A();

    A.prototype.name = "A"; 
    aObj.alertname(); // output is "A";
    bObj.alertname(); // output is "A";

    B.prototype.name = "B";
    aObj.alertname(); // output is "A";
    bObj.alertname(); // output is "B";

Q2:再次,继承与组合不同。当您指定B.prototype时,您不只是将A类型的对象放在占位符中,而是更改B类型的所有对象的“蓝图”。因此,当您访问所述蓝图时,您不会获得对象类型A的蓝图,但是包含对类型A的蓝图的引用的类型B的蓝图。该蓝图将不具有类型原型的成员,因为原型不是任何类的“常规”成员。将其添加到上面的代码中:

function iterateMembers ( obj ) {
    var str = "";
    for (var member in obj) {
        str += member + ", "
    }
    alert (str);
}

iterateMembers (aObj);
iterateMembers (A.prototype); 

注意aObj和A.prototype都不包含成员“prototype”。现在打电话

iterateMembers (A);
alert (typeof(A));

现在应该很明显,prototype是type函数的一个成员,并且由于函数不是由A或B继承的(事实上,它不能被继承),它们都不包含名字的成员“原型”。

答案 1 :(得分:1)

  

Q1:当我设置B的原型时,我不知道B的原型属性将在何时/如果A的原型更新时更新。我的意思是,对我而言,它只是继承/复制所有这些属性。

函数对象具有prototype字段:

function A(name) { this.name = name }

print(A.prototype) // [object Object]

使用new A创建对象时,生成的对象包含constructor字段,该字段是对构造函数的引用:

var a = new A('Eric')

print(a.constructor == A) // True
print(a.constructor.prototype == A.prototype) // True

如果您尝试索引a并且字段未定义,JavaScript将尝试通过a的原型(例如a.constructor.prototype)解析它。我们可以使用它来向所有A实例添加内容:

A.prototype.greet = function() { print('Hi, ' + this.name + '!') }

a.greet() // Hi, Eric!

此字段解析以递归方式工作。

function B(name) { this.name = name.toUpperCase() }
B.prototype = new A
b = new B("Eric")
b.greet() // Hi, ERIC!

最后一行中发生的事情是JavaScript在b中找不到“问候”字段,因此它会尝试b的原型。它也没有找到,所以它尝试* b的原型的原型,依此类推,直到它用完了原型。

  

口译员知道要切断A原型的属性:   B.prototype.prototype

没有什么被砍掉,你只是在看错了。你想要:

B.prototype.constructor.prototype