我有这个功能:
function Foo(){}
根据这张照片:
>> Foo.prototype -> Foo {}
所以,如果我写:
Foo.prototype.constructor
现在 - 它引用了构造函数,它创建了Foo{}
对象function Foo(){}
一切都好。
那么问题在哪里?
Foo.prototype
是一个对象实例 - > Foo {}
谁是Foo{}
的构造函数?
是function Foo(){}
你可以在这里看到黄色:
确定
但我被告知here:
因此Foo.prototype.__proto__
应该引用prototype
的{{1}}而不是function Foo(){}
!
如果我翻译它:
Object.prototype
但这是错误的
我可能错了,因为:
我错过了什么?
答案 0 :(得分:4)
注意:首先,__proto__
是非标准的,使用Object.getPrototypeOf
,虽然简短,而且因为我很懒,我确实使用了prototype
了不少在这个答案中的时间
好吧,如果我正确地读你的话,你会被你最初的假设所抛弃:
Foo.prototype -> Foo{}
根据定义,Foo
(它是构造函数)的原型是Foo
的实例。但是,因为构造函数是一个函数,并且构造函数返回特定实例的对象,所以原型将是增强的Object
。
我不是将原型无效性与经典OOP进行比较的忠实粉丝,但是想到这样:
Foo
原型是一种可变类定义(你可以随意添加方法和属性),构造函数创建一个扩充这个原型的对象,并添加另一个实例级别的属性/方法层
因此Foo.prototype instanceof Foo
是真的。但是,Foo
是一个对象:
Object.getPrototypeOf(Foo.prototype) === Object.prototype
是真的。就像
一样Object.getPrototypeOf(Array.prototype) === Object.prototype.
将其转换为JS(原型)-speak,你得到类似的东西:
对于JS创建的每个函数对象,都为此对象分配了prototype
属性。 prototype
属性是Object
的实例,但它有1个特殊属性
如果有人试图访问对象上的属性或方法,并且JS无法在实例级别找到此属性,JS将尝试解析prototype属性上的名称:
instance.nonExistantProperty;
//js scans instance variable, doesn't find property:
instance.prototype.nonExistantProperty
//js uses prototype, if not found:
instance.prototype.prototype.nonExistantProperty
//all the way up to Object.prototype, which does not have a prototype, so here an exception is raised (TypeError is thrown)
这是我从one of my older posts here复制的查找的简短示意图,可能值得一看,也检查底部的链接答案,他们会详细介绍这个问题
[ F.divide ]<=========================================================\ \
F[divide] ===> JS checks instance for property divide | |
/\ || | |
|| || --> property found @instance, return value-------------------------------| |
|| || | |
|| ===========> Function.prototype.divide could not be found, check prototype | |
|| || | |
|| ||--> property found @Function.prototype, return-----------------------| |
|| || | |
|| ==========> Object.prototype.divide: not found check prototype? | |
|| || | |
|| ||--> property found @Object.prototype, return---------------------|_|
|| || |=|
|| =======>prototype is null, return "undefined.divide"~~~~~~~~~~~~~~~|X|
|| \ /
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~< TypeError can't read property 'x' of undefined
基本上就是这样。
现在,也许你对Foo.prototype.constructor
引用Foo
函数的原因感到沮丧。
同样,这很容易,因为每个实例都应包含您可能需要的所有信息,以确定您正在处理的对象类型:
function Foo{}
var inst = new Foo();
console.log(inst.constructor);//references the constructor function
请记住,Foo
返回的所有实例都返回一个对象,该对象引用所有prototype
属性,以及(可选)实例级别的某些属性。
那么,为什么还要打扰创建这样的实例呢?同样,这非常简单:更改实例,不会更改原型:
console.log(Foo.prototype.constructor === inst.constructor);//true
inst.constructor = function(){};//override constructor property
console.log(Foo.prototype.constructor === inst.constructor);//false, prototype did not change