Javascript原型继承疑问二

为了更好地理解它,我在js中做了一些继承,并且发现了让我困惑的东西。

我知道当你用new关键字调用'构造函数'时,你会得到一个引用该函数原型的新对象。

我也知道,为了进行原型继承,您必须将构造函数的原型替换为您想成为“超类”的对象的实例。

所以我做了这个愚蠢的例子来尝试这些概念:

function Animal(){}
function Dog(){}

Animal.prototype.run = function(){alert("running...")};

Dog.prototype = new Animal(); 
Dog.prototype.bark = function(){alert("arf!")};

var fido = new Dog();
fido.bark() //ok
fido.run() //ok

console.log(Dog.prototype) // its an 'Object' 
console.log(fido.prototype) // UNDEFINED
console.log(fido.constructor.prototype == Dog.prototype) //this is true

function KillerDog(){};
KillerDog.prototype.deathBite = function(){alert("AAARFFF! *bite*")}

fido.prototype = new KillerDog();

console.log(fido.prototype) // no longer UNDEFINED
fido.deathBite(); // but this doesn't work!

(这是在Firebug的控制台中完成的)

1)为什么如果所有新对象都包含对创建者函数原型的引用,fido.prototype是未定义的?

2)是继承链[obj] - > [构造函数] - > [原型]而不是[obj] - > [原型]?

3)是我们的对象(fido)的“原型”属性吗? 如果是的话......为什么'deathBite'未定义(在最后一部分)?

谢谢!


1)为什么如果所有新对象都包含对创建者函数原型的引用,fido.prototype是未定义的?

所有新的对象都有一个对构造函数在施工时出现的原型的引用。 然而,用于存储此引用的属性名称不是prototype因为它在构造函数本身上。 一些Javascript实现允许通过某些属性名称(如__proto__访问此“隐藏”属性,而其他属性则不会(例如Microsofts)。

2)是继承链[obj] - > [构造函数] - > [原型]而不是[obj] - > [原型]?

不可以。看看这个: -

function Base() {}
Base.prototype.doThis = function() { alert("First"); }

function Base2() {}
Base2.prototype.doThis = function() { alert("Second"); }

function Derived() {}
Derived.prototype = new Base()

var x = new Derived()

Derived.prototype = new Base2()

x.doThis();

这提醒“第一”而不是第二。 如果继承链通过构造函数,我们会看到“Second”。 当一个对象被构造时,在Functions prototype属性中保存的当前引用被转移到其对原型的对象隐藏引用。

3)是我们的对象(fido)的“原型”属性吗? 如果是的话......为什么'deathBite'未定义(在最后一部分)?

为一个对象(Function除外)指定一个名为prototype的属性没有特别的意义,如前所述,对象不会通过这样的属性名称来维护对其原型的引用。


一旦用new的实例化了对象的原型,你就不能改变它。

在你上面的例子中,像

fido.prototype = new KillerDog();

只需在对象fido上创建一个名为prototype的新属性,并将该属性设置为新的KillerDog对象。 这与之相同

fido.foo = new KillerDog();

当你的代码站立...

// Doesn't work because objects can't be changed via their constructors
fido.deathBite();

// Does work, because objects can be changed dynamically, 
// and Javascript won't complain when you use prototype 
//as an object attribute name
fido.prototype.deathBite();

特殊的prototype行为仅适用于JavaScript中的构造function ,其中构造函数是function ,将用new function调用。


用数字回答你的问题:

  • 对象的原型属性不称为prototype 。 该标准使用[[prototype]]来指定它。 Firefox以__proto__的名称公开该属性。
  • 继承链是[obj][prototype object] 。 你的原始假设( [obj][constructor][prototype] )是不正确的,你可以通过修改constructor和/或constructor.prototype constructor .prototype并检查可以在你的[obj]上调用哪些方法来轻易否定它 -这些修改不会改变任何内容。
  • 对象的prototype属性不被检查和不使用。 你可以将它设置为任何你喜欢的。 JavaScript仅在对象构造期间在函数对象上使用它。
  • 为了演示#3这里是来自Dojo的代码:

    dojo.delegate = dojo._delegate = (function(){
      // boodman/crockford delegation w/ cornford optimization
      function TMP(){}
      return function(obj, props){
        TMP.prototype = obj;
        var tmp = new TMP();
        if(props){
          dojo._mixin(tmp, props);
        }
        return tmp; // Object
      }
    })();
    

    正如您所看到的,它利用了prototype仅用于一个地方的情况,即对于具有不同原型的所有委托对象重复使用相同的函数TMP 。 实际上,在使用new调用函数之前直接分配prototype ,并且在不影响任何创建的对象之后它将被更改。

    您可以在JavaScript中的[[Prototype]]和prototype之间的关系答案中找到创建对象的序列。

    链接地址: http://www.djcxy.com/p/30061.html

    上一篇: Javascript Prototypal Inheritance Doubt II

    下一篇: VS. prototype in JavaScript