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
我知道我不是第一个提出这个建议的人,但是找出它来发现它更有趣:-)。无论如何,之后我发现了另一个我认为基本相同的图表:
对我来说,最令人惊讶的事情是发现它Object.__proto__
指向Function.prototype
,而不是Object.prototype
,但是我相信有充分的理由:-)
我也将图像中提到的代码粘贴到这里,以便于任何人想要对其进行测试。请注意,一些属性已添加到对象中,以使一些跳转后的位置变得容易知道:
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
运算符创建对象时,其内部[[Prototype]]属性将设置为构造函数的prototype
属性所指向的对象。
这意味着.constructor
将评估为.__proto__.constructor
,即用于创建对象的构造函数,并且据我们了解,protoype
该函数的属性用于设置对象的[[Prototype]]。
随之而来的.constructor.prototype.constructor
是.constructor
(只要这些属性没有被覆盖);请参阅此处以获取更详细的说明。
如果__proto__
可用,您可以遍历对象的实际原型链。在普通的ECMAScript3中无法执行此操作,因为JavaScript并非为深度继承层次结构而设计。
JavaScript的原型继承是基于__proto__
属性的,即每个对象都继承其__proto__
属性所引用的对象的内容。
该prototype
属性仅对Function
对象特别适用,并且仅在使用new
operator调用Function
as构造函数时才具有。在这种情况下,创建的对象__proto__
将被设置为构造函数Function.prototype
。
这意味着添加到Function.prototype
将自动反映所有__proto__
引用的对象Function.prototype
。
Function.prototype
用另一个对象替换构造函数的对象将不会更新__proto__
任何现有对象的属性。
请注意,__proto__
不应直接访问属性,而应使用Object.getPrototypeOf(object)。
为了回答第一个问题,我创建了一个定制的__proto__
和prototype
参考图,不幸的是stackoverflow不允许我添加“少于10个信誉”的图像。也许另一些时间。
[Edit]该图[[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
属性在创建的对象中不存在,但是是从原型继承的。
Object
是夏娃,Function
也是亚当,亚当(Function
)使用其骨骼(Function.prototype
)创建了夏娃(Object
)。那谁创造了亚当(Function
)?-JavaScript语言的发明者:-)。
根据utsaina的回答,我想添加更多有用的信息。
对我来说,最令人惊讶的事情是发现它
Object.__proto__
指向Function.prototype
,而不是Object.prototype
,但是我相信有充分的理由:-)
不应该这样。 Object.__proto__
不应指向Object.prototype
。相反,实例Object
o
,o.__proto__
应指向Object.prototype
。
(请原谅我使用这些术语class
和instance
JavaScript,但您知道的是:-)
我认为类Object
本身是的一个实例Function
,因此Object.__proto__ === Function.prototype
。因此:Object
是夏娃,Function
也是亚当,亚当(Function
)使用其骨骼(Function.prototype
)创建夏娃(Object
)。
此外,即使类Function
本身也是其自身的实例Function
,即Function.__proto__ === Function.prototype
,这也是为什么Function === Function.constructor
此外,常规类Cat
是的实例Function
,即Cat.__proto__ === Function.prototype
。
发生上述情况的原因是,实际上,当我们使用JavaScript创建类时,我们只是在创建一个函数,该函数应该是的实例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
好。然后,谁创建了特殊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
运算符创建对象时,如果愿意,其内部[[Prototype]]
/proto__
属性将设置prototype
为其constructor function
或“创建者”的property(1)。 -
在JS中进行硬编码-:
Object.prototype.__proto__
isnull
。
让我们将这两点称为“ 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
更好?
每个函数都会创建其原型。当我们使用该函数构造函数创建对象时,我对象的__proto__属性将开始指向该函数的原型。
如果所有这些数字都是压倒性的,那么让我们看一下这些属性的含义。
STH.prototype
创建新函数时,将并行创建一个空对象,并使用[[Prototype]]
链将其链接到该函数。要访问该对象,我们使用 prototype
函数的属性。
function Gadget() {}
// in background, new object has been created
// we can access it with Gadget.prototype
// it looks somewhat like {constructor: Gadget}
请记住,prototype
属性仅可用于功能。
构造函数
上面提到的原型对象除了-以外没有其他属性constructor
。此属性表示创建原型对象的函数。
var toy = new Gadget();
在创建Gadget
函数时,我们还创建了一个对象,就像{constructor: Gadget}
-一样Gadget.prototype
。作为constructor
指创建的对象原型的函数,toy.constructor
表示Gadget
功能。我们写toy.constructor.prototype
,我们得到{constructor: Gadget}
又了。
因此,存在一个恶性循环:您可以使用toy.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype
,并且永远都是Gadget.prototype
。
toy
.constructor // Gadget
.prototype // {constructor: Gadget}
.constructor // Gadget
.prototype // {constructor: Gadget}
// ...
STH .__ proto__
虽然prototype
是特定于函数的属性,__proto__
但它位于中时可用于所有对象Object.prototype
。它指的是可以创建对象的函数原型。
[].__proto__ === Array.prototype
// true
({}).__proto === Object.prototype
// true
在这里toy.__proto__
是Gadget.prototype
。正如Gadget.prototype
对象({}
)和对象是通过Object
函数创建的一样(请参见上面的示例),我们得到Object.prototype
。这是JavaScript中的高级对象,__proto__
只能指示null
。
toy
.__proto__ // Gadget.prototype (object looking like {constructor: Gadget})
.__proto__ // Object.prototype (topmost object in JS)
.__proto__ // null - Object.prototype is the end of any chain
简短的答案:__proto__
是对prototype
创建对象的构造函数的属性的引用。
JavaScript中的对象
JavaScript对象是集合的内置类型零个或多个属性的。属性是保存其他对象,原始值或函数的容器。
JavaScript中的构造函数
函数是常规对象([[Call]]
以ECMA-262术语实现),具有可调用的附加功能,但在JavaScript中扮演另一个角色:如果通过调用它们,则它们将成为构造函数(对象的工厂)。new
运算符。因此,构造函数是其他语言类的粗略模拟。
每个JavaScript函数实际上都是Function
内置函数对象的一个实例,该实例具有一个特殊的名称,该名称prototype
用于实现基于原型的继承和共享属性。构造函数创建的每个对象都有对其构造函数值的隐式引用(称为原型__proto__
)prototype
。
构造函数prototype
是一种用于构建对象的蓝图,因为构造函数创建的每个对象都会继承对其的引用prototype
。
原型链
对象通过内部属性[[Prototype]]
或指定其原型__proto__
。两个对象之间的原型关系与继承有关:每个对象可以将另一个对象作为其原型。原型可能就是null
价值。
通过__proto__
属性连接的对象链称为原型链。当引用对象中的属性时,该引用是在原型链中包含该名称的属性的第一个对象中遇到的属性。原型链的行为就像是单个对象一样。
看到这张图片(摘自这个博客):
每当您尝试访问对象中的属性时,JavaScript都会在该对象中开始对其进行搜索,然后继续其原型,原型的原型等等,直到遇到该属性或是否__proto__
拥有value为止null
。
这种使用原型链的继承通常称为委托,以避免与使用类链的其他语言混淆。
几乎所有对象都是的实例Object
,因为Object.prototype
它们在原型链中位于最后。但Object.prototype
不是Object
因为Object.prototype.__proto__
持有价值的一个实例null
。
您还可以使用如下null
原型创建对象:
var dict = Object.create(null);
这样的对象比文字对象是更好的映射(字典),这就是为什么有时将这种模式称为dict模式(字典的dict)的原因。
注意:使用创建的文字对象{}
是的实例,Object
因为({}).__proto__
是对的引用Object.prototype
。
文章标签:inheritance , javascript , prototype-programming
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!
评论已关闭!