__proto__与constructor.prototype有什么不同?
function Gadget(name, color) { this.name = name; this.color = color; } Gadget.prototype.rating = 3 var newtoy = new Gadget("webcam", "black") newtoy.constructor.prototype.constructor.prototype.constructor.prototype
它总是返回评级= 3的对象。
但是,如果我做到以下几点:
newtoy.__proto__.__proto__.__proto__
链最终返回null
。
同样在Internet Explorer中,如果没有__proto__
属性,我将如何检查null?
最近我一直试图把这个“头像”包裹起来,终于想出了这张“地图”
http://i.stack.imgur.com/KFzI3.png
我知道我不是第一个完成这个工作,但是更有趣的发现它:-)。 无论如何,在那之后,我发现了另外一个我认为基本相同的图:
Javascript对象布局
对我来说最令人惊讶的是发现Object.__proto__
指向Function.prototype
,而不是Object.prototype
,但是我确信有一个很好的理由:-)
我粘贴图片中提到的代码,以及是否有人想testing它。 请注意,有些属性被添加到对象中,以便于在一些跳转之后知道我们的位置:
Object.O1=''; Object.prototype.Op1=''; Function.F1 = ''; Function.prototype.Fp1 = ''; Cat = function(){}; Cat.C1 = ''; Cat.prototype.Cp1 = ''; mycat = new Cat(); o = {}; // EDITED: using console.dir now instead of console.log console.dir(mycat); console.dir(o);
constructor
是由函数对象的prototype
属性指向的对象的预定义的[[DontEnum]]属性,并且最初将指向函数对象本身。
__proto__
相当于对象的内部[[Prototype]]属性,即它的实际原型。
当用new
运算符创build一个对象时,其内部[[Prototype]]属性将被设置为构造函数的prototype
属性所指向的对象。
这意味着.constructor
将评估为.__proto__.constructor
,也就是用于创build对象的构造函数,并且据我们protoype
,此函数的protoype
属性用于设置对象的[[Prototype]]。
因此, .constructor.prototype.constructor
是一样的(只要这些属性没有被覆盖)。 在这里看到更详细的解释。
如果__proto__
可用,则可以走对象的实际原型链。 在简单的ECMAScript3中没有办法做到这一点,因为JavaScript不是为深层inheritance层次而devise的。
JavaScript中的原型inheritance是基于__proto__
属性,因为每个对象都inheritance了__proto__
属性引用的对象的内容。
prototype
属性仅适用于Function
对象,只有在使用new
运算符来调用Function
作为构造Function
时才是如此。 在这种情况下,创build的对象的__proto__
将被设置为构造函数的Function.prototype
。
这意味着添加到Function.prototype
将自动反映__proto__
引用Function.prototype
所有对象。
用另一个对象replace构造函数的Function.prototype
不会更新任何已经存在的对象的__proto__
属性。
请注意,不应该直接访问__proto__
属性,而应该使用Object.getPrototypeOf(object) 。
为了回答第一个问题,我创build了一个定制的__proto__
和prototype
参考图,不幸的是,stackoverflow不允许我添加“less于10个声望”的图片。 也许有些时候
[编辑]该图使用[[Prototype]]
而不是__proto__
因为ECMAScript规范是如何引用内部对象的。 我希望你能把一切都弄清楚。
这里有一些提示可以帮助你理解这个数字:
red = JavaScript Function constructor and its prototype violet = JavaScript Object constructor and its prototype green = user-created objects (first created using Object constructor or object literal {}, second using user-defined constructor function) blue = user-defined function and its prototype (when you create a function, two objects are created in memory: the function and its prototype)
请注意, constructor
属性不存在于创build的对象中,而是从原型inheritance。
Object
是Eve, Function
是Adam,Adam( Function
)用他的骨骼( Function.prototype
)创buildEve( Object
)。 那么谁创造了亚当( Function
)? – JavaScript语言的发明者:-)。
根据utsaina的回答,我想添加更多有用的信息。
对我来说最令人惊讶的是发现
Object.__proto__
指向Function.prototype
,而不是Object.prototype
,但是我确信有一个很好的理由:-)
它不应该。 Object.__proto__
不应该指向Object.prototype
。 相反, Object
o
, o.__proto__
的实例应该指向Object.prototype
。
(原谅我在JavaScript中使用术语class
和instance
,但你知道它:-)
我认为类Object
本身是Function
一个实例,这就是为什么Object.__proto__ === Function.prototype
。 因此: Object
是Eve, Function
是Adam,Adam( Function
)使用他的骨骼( Function.prototype
)来创buildEve( Object
)。
此外,即使是类Function
本身也是Function
本身的一个实例,即Function.__proto__ === Function.prototype
,这也是为什么Function === Function.constructor
此外,常规类Cat
是Function
一个实例,即Cat.__proto__ === Function.prototype
。
以上的原因是,当我们在JavaScript中创build一个类时,实际上我们只是创build了一个函数,它应该是Function
一个实例。 Object
和Function
是特殊的,但它们仍然是类,而Cat
是一个普通的类。
作为一个因素,在Google Chrome JavaScript引擎中,以下4个:
-
Function.prototype
-
Function.__proto__
-
Object.__proto__
-
Cat.__proto__
它们都是===
(绝对相等)到其他3,它们的值是function Empty() {}
> Function.prototype function Empty() {} > Function.__proto__ function Empty() {} > Object.__proto__ function Empty() {} > Cat.__proto__ function Empty() {} > Function.prototype === Function.__proto__ true > Function.__proto__ === Object.__proto__ true > Object.__proto__ === Cat.__proto__ true
好。 那么谁创build了特殊function Empty() {}
( Function.prototype
)? 想想看:-)
我真的不知道为什么人们没有把你的理解中的实际问题纠正在哪里。
这会让你更容易发现问题
那么让我们看看发生了什么事情:
var newtoy = new Gadget("webcam", "black") newtoy .constructor //newtoy's constructor function is newtoy ( the function itself) .prototype // the function has a prototype property.( all functions has) .constructor // constructor here is a **property** (why ? becuase you just did `prototype.constructor`... see the dot ? ) ! it is not(!) the constructor function !!! this is where your mess begins. it points back to the constructor function itself ( newtoy function) .prototype // so again we are at line 3 of this code snippet .constructor //same as line 4 ... .prototype rating = 3
太棒了,现在让我们来看看这个__proto__
在此之前,请记住关于__proto__
两件事:
-
当你使用
new
运算符创build一个对象时,如果你愿意的话,它的内部[[Prototype]]
/proto__
属性将被设置为它的constructor function
的prototype
属性(1)或者“creator”。 -
硬编码在JS – :
Object.prototype.__proto__
为null
。
我们把这两点称为“ bill
”
newtoy .__proto__ // When `newtoy` was created , Js put __proto__'s value equal to the value of the cunstructor's prototype value. which is `Gadget.prototype`. .__proto__ // Ok so now our starting point is `Gadget.prototype`. so regarding "bill" who is the constructor function now? watch out !! it's a simple object ! a regular object ! prototype is a regular object!! so who is the constructor function of that object ? Right , it's the `function Object(){...}`. Ok .( continuing "bill" ) does it has a `prototype` property ? sure. all function has. it's `Object.prototype`. just remember that when Gadget.prototype was created , it's internal `__proto__` was refered to `Object.prototype` becuase as "bill" says :"..will be set to the `prototype` property of its `constructor function`" .__proto__ // Ok so now our satrting point is `Object.prototype`. STOP. read bullet 2.Object.prototype.__proto__ is null by definition. when Object.prototype ( as an object) was created , they SET THE __PROTO__ AS NULL HARDCODED
更好?
每个function创build它的原型。 当我们使用该函数构造函数创build对象时,我的对象的__proto__属性将开始指向该函数的原型。