我在js做了一些继承,以便更好地理解它,我发现了让我困惑的东西.
我知道当你用new关键字调用'constructor function'时,你得到一个新对象,引用该函数的原型.
我也知道,为了进行原型继承,你必须用你想成为'超类'的对象的实例替换构造函数的原型.
所以我做了这个愚蠢的例子来尝试这些概念:
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)为什么如果所有新对象都包含对creator函数原型的引用,fido.prototype是未定义的?
2)继承链[obj] - > [constructor] - > [prototype]而不是[obj] - > [prototype]?
3)我们的对象(fido)的"原型"属性是否曾被检查过?如果是这样的话......为什么'deathBite'未定义(在最后一部分)?
1)为什么如果所有新对象都包含对creator函数原型的引用,fido.prototype是未定义的?
所有新对象都会在构造时对其构造函数中存在的原型进行引用.但是,用于存储此引用的属性名称prototype
与构造函数本身不同.一些Javascript实现允许通过某些属性名称访问这个"隐藏"属性,就像__proto__
其他属性名称一样(例如微软).
2)继承链[obj] - > [constructor] - > [prototype]而不是[obj] - > [prototype]?
不.看看这个: -
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".构造对象时,函数prototype属性中保存的当前引用将转移到其原型的对象隐藏引用.
3)我们的对象(fido)的"原型"属性是否曾被检查过?如果是这样的话......为什么'deathBite'未定义(在最后一部分)?
分配给一个对象(函数除外)一个被调用的属性prototype
没有特殊含义,如前所述,一个对象不通过这样的属性名维护对其原型的引用.
一旦对象的原型被实例化,就无法更改它new
.
在上面的例子中,行如
fido.prototype = new KillerDog();
只需创建一个prototype
在对象上命名的新属性fido
,并将该属性设置为一个新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
将被调用的new
.