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] -> [构造函数]-> [prototype] 而不是 [obj] -> [原型] ?
3)我们的对象(fido)的“prototype”属性是否被检查过? 如果是这样...为什么'deathBite'未定义(在最后一部分)?
I'been doing some inheritance in js in order to understand it better, and I found something that confuses me.
I know that when you call an 'constructor function' with the new keyword, you get a new object with a reference to that function's prototype.
I also know that in order to make prototypal inheritance you must replace the prototype of the constructor function with an instance of the object you want to be the 'superclass'.
So I did this silly example to try these concepts:
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!
(This was done in Firebug's console)
1) Why if all new objects contain a reference to the creator function's prototype, fido.prototype is undefined?
2) Is the inheritance chain [obj] -> [constructor] -> [prototype] instead of [obj] -> [prototype] ?
3) is the 'prototype' property of our object (fido) ever checked? if so... why is 'deathBite' undefined (in the last part)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
所有新对象都保留对其构造函数在构造时存在的原型的引用。 然而,用于存储此引用的属性名称不是原型,因为它位于构造函数本身。 某些 Javascript 实现确实允许通过某些属性名称(如 __proto__)访问此“隐藏”属性,而其他实现则不允许(例如 Microsoft)。
不,看看这个:-
这提醒“第一”而不是第二。 如果继承链通过构造函数,我们会看到“Second”。 当构造一个对象时,Functions 原型属性中保存的当前引用将转移到该对象对其原型的隐藏引用。
为对象(函数除外)分配一个名为
prototype
的属性没有特殊含义,如前所述,对象不会通过这样的属性名称维护对其原型的引用。All new objects do hold a reference to the prototype that was present on their constructor at the time of construction. However the property name used to store this reference is not
prototype
as it is on the constructor function itself. Some Javascript implementations do allow access to this 'hidden' property via some property name like__proto__
where others do not (for example Microsofts).No. Take a look at this:-
This alerts "First" not Second. If the inheritance chain went via the constructor we would see "Second". When an object is constructed the current reference held in the Functions prototype property is transfered to the object hidden reference to its prototype.
Assigning to an object (other than a Function) a property called
prototype
has no special meaning, as stated earlier an object does not maintain a reference to its prototype via such a property name.一旦使用
new
实例化对象,就无法更改其原型。在上面的示例中,类似这样的行
只是在对象
fido
上创建一个名为prototype
的新属性,并将该属性设置为新的KillerDog
对象。 没有什么不同这与您的代码
...特殊的
prototype
行为仅适用于 javascript 中的构造函数,其中构造函数是用new 调用的
。函数
You cannot change an object's prototype once it's been instantiated with
new
.In your example above, lines like
simply creates a new attribute named
prototype
on the objectfido
, and sets that attribute to a newKillerDog
object. It's no different thanAs your code stands...
The special
prototype
behavior applies only to constructors in javascript, where constructors arefunction
s that will be called withnew
.用数字回答你的问题:
prototype
。 标准使用[[prototype]]
来指定它。 Firefox 以 __proto__ 的名义公开此属性。[obj]
⇒[prototype object]
。 您最初的假设 ([obj]
⇒[constructor]
⇒[prototype]
) 是不正确的,您可以通过修改轻松反驳它constructor
和/或constructor.prototype
,并检查可以在[obj]
上调用哪些方法 - 您会发现这些修改不会改变任何内容。prototype
属性不会被检查和使用。 您可以将其设置为您喜欢的任何值。 JavaScript 仅在对象构造期间在函数对象上使用它。为了演示#3,这里是来自 Dojo 的代码:
如您所见,它利用了以下事实:
prototype
仅在一处使用,通过为具有不同原型的所有委托对象重用相同的函数TMP
来实现。 事实上,prototype
是在使用new
调用函数之前直接赋值的,之后它会被更改,不会影响任何创建的对象。您可以在我对 [Prototype 之间的关系]] 和 JavaScript 中的原型。
Answer by numbers to your questions:
prototype
. The standard uses[[prototype]]
to designate it. Firefox makes this property public under the name of __proto__.[obj]
⇒[prototype object]
. Your original assumption ([obj]
⇒[constructor]
⇒[prototype]
) is incorrect and you can easily disprove it by modifyingconstructor
and/orconstructor.prototype
, and checking what methods can be called on your[obj]
— you will discover that these modifications do not change anything.prototype
property on objects are not checked and not used. You can set it to whatever you like. JavaScript uses it on function objects only during the object construction.To demonstrate the #3 here is the code from Dojo:
As you can see it takes advantage of the fact that
prototype
is used only in one place by reusing the same functionTMP
for all delegated objects with different prototypes. In factprototype
is assigned directly before invoking the function withnew
, and it will be changed after that not affecting any created objects.You can find the object created sequence in my answer to Relation between [[Prototype]] and prototype in JavaScript.
我知道这个问题已经得到解答,但是,有更好的方法来进行继承。 仅仅为了继承的目的而调用构造函数是不可取的。 不良影响之一是。
现在,您已将属性“a”添加到了 Child 的原型中,但您并不打算这样做。
这是正确的方法(我没有发明这个,Ext-JS和其他库使用这个)
更简单的方法是添加第三个参数来扩展您指定派生类方法的位置,这样您就不必调用扩展,然后向原型添加方法
然后,您还可以为语法糖做很多其他事情。
关于它的博客:http://js-bits。 blogspot.com/2010/08/javascript-inheritance-done-right.html
I know it's already been answered but, there's a better way to do inheritance. Calling a constructor just for the purpose of inheritance is not desirable. One of the undesired effects is.
Now You've added property "a" to the prototype of Child that you didn't intend to.
Here's the right way (I didn't invent this, Ext-JS and other libs use this)
An even easier way is to add a third parameter to extend where you specify the method of the derived class so that you don't have to call extend and then add methods to the prototype
Then there are many other things you could do for syntactic sugar.
Blogged about it: http://js-bits.blogspot.com/2010/08/javascript-inheritance-done-right.html
值得注意的是,在 ECMAScript 5(即 JavaScript 语言的最新版本)中,您可以通过
Object.getPrototypeOf
:Worth noting that in ECMAScript 5 (i.e. the latest version of the JavaScript language) you can get access to the internal [[Prototype]] property of an instance via
Object.getPrototypeOf
: