简体   繁体   English

Javascript __proto__ - 澄清?

[英]Javascript __proto__ - clarification?

I have this function : 我有这个功能:

function Foo(){}

According to this picture : 根据这张图片:

在此输入图像描述

>> Foo.prototype   ->    Foo {}

在此输入图像描述

So if I write : 所以,如果我写:

Foo.prototype.constructor Foo.prototype.constructor

Now - it references to the constructor function which created the Foo{} object which is function Foo(){} 现在 - 它引用了构造函数 ,它创建了Foo{}对象,它是function Foo(){}

在此输入图像描述

All ok. 一切都好。

So where is the question ? 那问题在哪里?

Foo.prototype is an object instance --> Foo {} Foo.prototype是一个对象实例 - > Foo {}

And who is the constructor function of Foo{} ? 谁是Foo{}的构造函数?

it is the the function Foo(){} 它是function Foo(){}

you can see it here in yellow : 你可以在这里看到黄色:

在此输入图像描述

ok

But I was told here that : 但我在这里被告知:

在此输入图像描述

So Foo.prototype.__proto__ should reference to the prototype of function Foo(){} and not to Object.prototype ! 所以Foo.prototype.__proto__应该引用function Foo(){}prototype而不是Object.prototype

If I translate it : 如果我翻译它:

    __proto__               is the                   ctor's                        prototype
    _________________________________________________________________________________________
  Foo.prototype.__proto__     is the               function Foo(){}               Foo.prototype

but this is wrong 但这是错误的

And i'm probably wrong because : 我可能错了,因为:

在此输入图像描述

What am I missing ? 我错过了什么?

Note: First off, __proto__ is non-standard, use Object.getPrototypeOf , though for shortness, and because I'm lazy, I did use prototype quite a few times in this answer 注意:首先, __proto__是非标准的,使用Object.getPrototypeOf ,虽然为了Object.getPrototypeOf ,因为我很懒,我在这个答案中确实使用了prototype很多次

Well, you're thrown of by your initial assumption, if I'm reading you correctly: 好吧,如果我正确地读你,你会被最初的假设所抛弃:

Foo.prototype -> Foo{}

The prototype of Foo (which is a constructor) is, by definition an instance of Foo . 根据定义, Foo的原型(它是一个构造函数)是Foo一个实例。 But, because a constructor is a function, and a constructor returns an object of a particular instance, the prototype will be an augmented Object either way. 但是,因为构造函数是一个函数,并且构造函数返回特定实例的对象,所以原型将是一个增强的Object
I'm not a big fan of comparing prototypal ineritance to classical OOP, but think of it like this: 我不是将原型无效性与经典OOP进行比较的忠实粉丝,但是想到这样:

The Foo prototype is sort of a mutable class definition (you can add methods and properties as you go along), the constructor creates an object that augments this prototype, and adds another layer of properties/methods on an instance level. Foo原型是一种可变类定义(您可以随意添加方法和属性),构造函数创建一个对象来扩充此原型,并在实例级别添加另一层属性/方法。
Hence Foo.prototype instanceof Foo is true. 因此Foo.prototype instanceof Foo是真的。 But, Foo being an object: 但是, Foo是一个对象:

Object.getPrototypeOf(Foo.prototype) === Object.prototype

is true. 是真的。 Just as 就像

Object.getPrototypeOf(Array.prototype) === Object.prototype.

Translate this to JS (prototype)-speak, and you get something like: 把它翻译成JS(原型)-speak,你会得到类似的东西:

For each function object JS creates, this object is assigned a prototype property. 对于JS创建的每个函数对象,为该对象分配一个prototype属性。 The prototype property is an instance of Object , but it has 1 special property. prototype属性是Object一个实例,但它有一个特殊属性。
If one attempts to access a property or method on an object, and JS cannot find this property defined at the instance level, JS will attempt to resolve the name on the prototype property: 如果有人试图访问对象上的属性或方法,并且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)

Here's a short schematic representation of this lookup, which I copied from one of my older posts here , it might be worth a look, also check the linked answers at the bottom, they go into even more details on this matter 这是这个查找的简短示意图,我从这里的一个旧帖子中复制 ,可能值得一看,也可以查看底部的链接答案,他们会详细介绍这个问题

[      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

That's basically it. 基本上就是这样。

Now, perhaps you're also a tad thwarted as to why Foo.prototype.constructor references the Foo function. 现在,也许你对于为什么Foo.prototype.constructor引用Foo函数有点挫败。
Again, this is quite easy, because each instance is expected to contain all information you might require to determine which type of object you're dealing with: 同样,这很容易,因为每个实例都应包含您可能需要的所有信息,以确定您正在处理的对象类型:

function Foo{}
var inst = new Foo();
console.log(inst.constructor);//references the constructor function

Remember, all instances returned by Foo return an object, that references all of the prototype properties, and (optionally) some properties at instance level, too. 请记住, Foo返回的所有实例都返回一个对象,该对象引用所有prototype属性,以及(可选)实例级别的某些属性。

Why, then, would you even bother creating such instances? 那么,为什么还要打扰创建这样的实例呢? Again this is perfectly simple: changing an instance, does not change the 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM