简体   繁体   English

__proto__ 与 constructor.prototype 有何不同?

[英]How does __proto__ differ from 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 

It always returns the object with rating = 3.它总是返回 rating = 3 的对象。

But if I do the following:但是,如果我执行以下操作:

newtoy.__proto__.__proto__.__proto__

The chain ends up returning null .该链最终返回null

Also in Internet Explorer how would I check the null if there is not a __proto__ property?同样在 Internet Explorer 中,如果没有__proto__属性,我将如何检查 null?

I've been trying to wrap my head around this recently and finally came up with this "map" that I think sheds full light over the matter我最近一直在努力解决这个问题,最后想出了这张“地图”,我认为它可以充分说明这个问题

http://i.stack.imgur.com/KFzI3.png http://i.stack.imgur.com/KFzI3.png在此处输入图像描述

I know I'm not the first one making this up but it was more interesting figuring it out that finding it:-).我知道我不是第一个编造这个的人,但弄清楚它比找到它更有趣:-)。 Anyway, after that I found eg this another diagram that I think says basicly the same:无论如何,在那之后我发现了另一个我认为基本相同的图表:

Javascript object layout Javascript object 布局

The most surprising thing for me was discovering that Object.__proto__ points to Function.prototype , instead of Object.prototype , but I'm sure there's a good reason for that:-)对我来说最令人惊讶的是发现Object.__proto__指向Function.prototype ,而不是Object.prototype ,这是一个很好的理由,但是)

I paste the code mentioned in the image here as well for if anyone wants to test it.如果有人想测试它,我也会在此处粘贴图像中提到的代码。 Note that some properties are added to the objects for making easy to know where we are after some jumps:请注意,一些属性被添加到对象中,以便在一些跳转后轻松知道我们在哪里:

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 is a pre-defined [[DontEnum]] property of the object pointed to by the prototype property of a function object and will initially point to the function object itself. constructor is a pre-defined [[DontEnum]] property of the object pointed to by the prototype property of a function object and will initially point to the function object itself.

__proto__ is equivalent to the internal [[Prototype]] property of an object, ie its actual prototype. __proto__等价于 object 的内部 [[Prototype]] 属性,即它的实际原型。

When you create an object with the new operator, its internal [[Prototype]] property will be set to the object pointed to by the constructor function's prototype property.当您使用new运算符创建 object 时,其内部 [[Prototype]] 属性将设置为构造函数的prototype属性指向的 object。

This means that .constructor will evaluate to .__proto__.constructor , ie the constructor function used to create the object, and as we have learned, the protoype property of this function was used to set the object's [[Prototype]]. This means that .constructor will evaluate to .__proto__.constructor , ie the constructor function used to create the object, and as we have learned, the protoype property of this function was used to set the object's [[Prototype]].

It follows that .constructor.prototype.constructor is identical to .constructor (as long as these properties haven't been overwritten);因此.constructor .constructor.prototype.constructor (只要这些属性没有被覆盖); see here for a more detailed explanation.有关更详细的说明,请参见此处

If __proto__ is available, you can walk the actual prototype chain of the object.如果__proto__可用,您可以走 object 的实际原型链。 There's no way to do this in plain ECMAScript3 because JavaScript wasn't designed for deep inheritance hierarchies.在普通的 ECMAScript3 中没有办法做到这一点,因为 JavaScript 不是为深层 inheritance 层次结构设计的。

The Prototypal Inheritance in JavaScript is based on __proto__ property in a sense that each object is inheriting the contents of the object referenced by its __proto__ property. The Prototypal Inheritance in JavaScript is based on __proto__ property in a sense that each object is inheriting the contents of the object referenced by its __proto__ property.

The prototype property is special only for Function objects and only when using new operator to call a Function as constructor. prototype属性仅对Function对象和使用new运算符调用Function作为构造函数时是特殊的。 In this case, the created object's __proto__ will be set to constructor's Function.prototype .在这种情况下,创建对象的__proto__将设置为构造函数的Function.prototype

This means that adding to Function.prototype will automatically reflect on all objects whose __proto__ is referencing the Function.prototype .这意味着添加到Function.prototype将自动反映其__proto__引用Function.prototype的所有对象。

Replacing constructor's Function.prototype with another object will not update __proto__ property for any of the already existing objects.将构造函数的Function.prototype替换为另一个 object不会更新任何现有对象的__proto__属性。

Note that __proto__ property should not be accessed directly, Object.getPrototypeOf(object) should be used instead.请注意,不应直接访问__proto__属性,应使用Object.getPrototypeOf(object)代替。

To answer the first question, I've created a bespoke diagram of __proto__ and prototype references, unfortunately stackoverflow does not allow me to add the image with "less than 10 reputation".为了回答第一个问题,我创建了一个__proto__prototype参考的定制图表,不幸的是,stackoverflow 不允许我添加“低于 10 名声望”的图像。 Maybe some other time.也许其他时间。

[Edit] The figure uses [[Prototype]] instead of __proto__ because that is how ECMAScript specification refers to internal objects. [编辑] 该图使用[[Prototype]]而不是__proto__因为这就是 ECMAScript 规范引用内部对象的方式。 I hope you can figure everything out.我希望你能弄清楚一切。

Here are some hints to help you understand the figure:这里有一些提示可以帮助您理解该图:

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)

Note that constructor property does not exist in created objects, but is inherited from the prototype.请注意, constructor属性不存在于创建的对象中,而是从原型继承的。

在此处输入图像描述

Object is Eve, and Function is Adam, Adam ( Function ) uses his bone ( Function.prototype ) to create Eve ( Object ). Object is Eve, and Function is Adam, Adam ( Function ) uses his bone ( Function.prototype ) to create Eve ( Object ). Then who created Adam ( Function )?那么是谁创造了亚当( Function )? -- The Inventor of the JavaScript language:-). -- JavaScript 语言的发明者:-)。

According to utsaina's answer, I want to add more useful info.根据 utsaina 的回答,我想添加更多有用的信息。

The most surprising thing for me was discovering that Object.__proto__ points to Function.prototype , instead of Object.prototype , but I'm sure there's a good reason for that:-)对我来说最令人惊讶的是发现Object.__proto__指向Function.prototype ,而不是Object.prototype ,这是一个很好的理由,但是)

It should NOT be.不应该。 Object.__proto__ should NOT point to Object.prototype . Object.__proto__不应指向Object.prototype Instead, the instance of Object o , o.__proto__ should point to Object.prototype .相反, Object o , o.__proto__的实例应该指向Object.prototype

(Forgive me for using the terms class and instance in JavaScript, but you know it:-) (请原谅我在 JavaScript 中使用术语classinstance ,但您知道的:-)

I think the class Object itself is an instance of Function , that's why Object.__proto__ === Function.prototype . I think the class Object itself is an instance of Function , that's why Object.__proto__ === Function.prototype . Therefore: Object is Eve, and Function is Adam, Adam ( Function ) uses his bone ( Function.prototype ) to create Eve ( Object ). Therefore: Object is Eve, and Function is Adam, Adam ( Function ) uses his bone ( Function.prototype ) to create Eve ( Object ).

Furthermore, even the class Function itself is an instance of Function itself, that is Function.__proto__ === Function.prototype , that's also why Function === Function.constructor Furthermore, even the class Function itself is an instance of Function itself, that is Function.__proto__ === Function.prototype , that's also why Function === Function.constructor

Further furthermore, the regular class Cat is an instance of Function , that is Cat.__proto__ === Function.prototype .此外,常规的 class CatFunction的一个实例,即Cat.__proto__ === Function.prototype

The reason for the above is, when we create a class in JavaScript, actually, we are just creating a function, which should be an instance of Function . The reason for the above is, when we create a class in JavaScript, actually, we are just creating a function, which should be an instance of Function . Object and Function are just special, but they are still classes, while Cat is a regular class. ObjectFunction只是特殊的,但它们仍然是类,而Cat是常规的 class。

As a matter of factor, in Google Chrome JavaScript engine, the following 4:作为一个因素,在 Google Chrome JavaScript 引擎中,以下 4:

  • Function.prototype
  • Function.__proto__
  • Object.__proto__
  • Cat.__proto__

They are all === (absolutely equal) to the other 3, and their value is function Empty() {}它们都=== (绝对等于)其他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

OK.好的。 Then who creates the special function Empty() {} ( Function.prototype )?那么谁来创建特殊的function Empty() {} ( Function.prototype )? Think about it:-)想一想:-)

I really don't know why people didn't correct you about where the actual problem in your understanding.我真的不知道为什么人们没有纠正你关于你理解的实际问题的地方。

This would make a lot easier for you to spot the problem这将使您更容易发现问题

So let's see what's going on:那么让我们看看发生了什么:

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

Great, so now let's look at this __proto__太好了,现在让我们看看这个__proto__

Before that, please remember 2 things regarding __proto__ :在此之前,请记住关于__proto__的两件事:

  1. When you create an object with the new operator, its internal [[Prototype]] / proto__ property will be set to the prototype property(1) of its constructor function or "creator" if you like.当您使用new运算符创建 object 时,其内部[[Prototype]] / proto__属性将设置为其constructor function或“创建者”的prototype属性(1),如果您愿意。

  2. Hard coded within JS —: Object.prototype.__proto__ is null .在 JS 中硬编码——: Object.prototype.__proto__null

Let's refer to these 2 points as " bill "让我们将这两点称为“ 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

Better?更好的?

Every functions creates it's prototype.每个函数都会创建它的原型。 And when we create an object using that function constructor then the __proto__ property of my object will start pointing to the prototype of that function. And when we create an object using that function constructor then the __proto__ property of my object will start pointing to the prototype of that function.

If all those figures were overwhelming, let's take a look what the properties mean.如果所有这些数字都是压倒性的,那么让我们来看看这些属性的含义。

STH.prototype

When creating a new function, there is an empty object being created in parallel and linked to the function with [[Prototype]] chain.在创建新的 function 时,会并行创建一个空的 object,并使用[[Prototype]]链链接到 function。 To access this object, we use prototype property of the function.要访问此 object,我们使用 function 的prototype属性。

function Gadget() {}
// in background, new object has been created
// we can access it with Gadget.prototype
// it looks somewhat like {constructor: Gadget}

Bear in mind that prototype property is only available for functions.请记住, prototype属性仅适用于函数。

STH.constructor STH.constructor

The prototype object mentioned above has no properties except for one - constructor .上面提到的原型object除了一个constructor外没有其他属性。 This property represents a function that created the prototype object.此属性表示创建原型 object 的 function。

var toy = new Gadget();

When creating Gadget function, we created an object like {constructor: Gadget} as well - that is nothing like Gadget.prototype .在创建Gadget function 时,我们创建了一个 object 就像{constructor: Gadget}一样 - 这与Gadget.prototype As constructor refers to a function that created an object prototype, toy.constructor represents Gadget function.由于constructor指的是创建 object 原型的 function, toy.constructor代表Gadget function。 We write toy.constructor.prototype and we are getting {constructor: Gadget} again.我们编写toy.constructor.prototype并且我们又得到了{constructor: Gadget}

Therefore, there's a vicious circle: you can use toy.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype and it always will be Gadget.prototype .因此,有一个恶性循环:你可以使用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__ STH.__proto__

While prototype is a property specific for functions, __proto__ is available for all objects as it lays in Object.prototype .虽然prototype是特定于函数的属性,但__proto__可用于所有对象,因为它位于Object.prototype中。 It refers to prototype of a function that can create an object.它是指可以创建 object 的 function 的原型。

[].__proto__ === Array.prototype
// true

({}).__proto === Object.prototype
// true

Here, toy.__proto__ is Gadget.prototype .在这里, toy.__proto__Gadget.prototype As Gadget.prototype is an object ( {} ) and objects are created with Object function (see the example above), we get Object.prototype . As Gadget.prototype is an object ( {} ) and objects are created with Object function (see the example above), we get Object.prototype . This is the higher object in JavaScript and its __proto__ can only indicate null .这是 JavaScript 中较高的 object ,它的__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

Short answer: __proto__ is a reference to the prototype property of the constructor that created the object.简短回答:__ __proto__是对创建 object 的构造函数的prototype属性的引用。

Objects in JavaScript JavaScript 中的对象

A JavaScript object is a built-in type for a collection of zero or more properties. JavaScript object 是用于零个或多个属性集合的内置类型。 Properties are containers that hold other objects, primitive values, or functions.属性是保存其他对象、原始值或函数的容器。

Constructors in JavaScript JavaScript 中的构造函数

Functions are regular objects (which implement [[Call]] in ECMA-262 terms) with the additional capability of being callable but play another role in JavaScript: they become constructors ( factories for objects) if invoked via the new operator.函数是常规对象(在 ECMA-262 术语中实现[[Call]] ),具有可调用的附加功能,但在 JavaScript 中扮演另一个角色:如果通过new运算符调用,它们将成为构造函数(对象的工厂)。 Constructors are thus a rough analog to classes in other languages.因此,构造函数粗略地类似于其他语言中的类。

Every JavaScript function is actually an instance of the Function built-in function object that has a special property named prototype used to implement prototype-based inheritance and shared properties. Every JavaScript function is actually an instance of the Function built-in function object that has a special property named prototype used to implement prototype-based inheritance and shared properties. Every object created by a constructor function has an implicit reference (called the prototype or __proto__ ) to the value of its constructor prototype .每个由构造函数 function 创建的 object 都有一个对其构造函数prototype的值的隐式引用(称为原型或__proto__ )。

The constructor prototype is a sort of blueprint for building objects since every object created by the constructor inherits a reference to its prototype .构造函数prototype是一种构建对象的蓝图,因为构造函数创建的每个 object 都继承了对其prototype的引用。

The prototype chain原型链

An object specifies its prototype via the internal property [[Prototype]] or __proto__ . object 通过内部属性[[Prototype]]__proto__指定其原型。 The prototype relationship between two objects is about inheritance: every object can have another object as its prototype.两个对象之间的原型关系大约是 inheritance:每个 object 可以有另一个 object 作为其原型。 The prototype may be the null value.原型可能是null值。

The chain of objects connected by the __proto__ property is called the prototype chain .__proto__属性连接的对象链称为原型链 When a reference is made to a property in an object, that reference is to the property encountered in the first object in the prototype chain that contains a property of that name.当引用 object 中的属性时,该引用是指原型链中包含该名称的属性的第一个 object 中遇到的属性。 The prototype chain behaves as if it were a single object.原型链的行为就像是单个 object。

See this image (extracted from this blog ):看到这张图片(从这个博客中提取):

原型.jpg

Whenever you try to access a property in an object, JavaScript starts the search for it in that object and continues with its prototype, the prototype's prototype and so on until the property is encountered or if __proto__ holds the value null . Whenever you try to access a property in an object, JavaScript starts the search for it in that object and continues with its prototype, the prototype's prototype and so on until the property is encountered or if __proto__ holds the value null .

This type of inheritance using the prototype chain is often called delegation to avoid confusion with other languages using the class chain.这种使用原型链的 inheritance 通常称为委托,以避免与使用 class 链的其他语言混淆。

Almost all objects are instances of Object , because Object.prototype is last in their prototype chain.几乎所有对象都是Object的实例,因为Object.prototype是其原型链中的最后一个。 But Object.prototype is not an instance of Object because Object.prototype.__proto__ holds the value null . But Object.prototype is not an instance of Object because Object.prototype.__proto__ holds the value null .

You can also create an object with a null prototype like this:您还可以使用null原型创建 object,如下所示:

var dict = Object.create(null);

Such an object is a better map (dictionary) than a literal object, which is why this pattern is sometimes called the dict pattern ( dict for dictionary).这样的 object 是比字面 object 更好的 map(字典),这就是为什么这种模式有时被称为字典模式(字典的字典)。

Note: literal objects created using {} are instances of Object since ({}).__proto__ is a reference to Object.prototype .注意:使用{}创建的文字对象是Object的实例,因为({}).__proto__是对Object.prototype的引用。

Prototypes in JavaScript are confusing for Everyone JavaScript 中的原型让每个人都感到困惑

Here is a simpler explanation.这是一个更简单的解释。 Below is how most objects in JavaScript inherit starting with null down to the object type:以下是 JavaScript 中的大多数对象如何从 null 开始继承到对象类型:

String   < Function < Object < null
Array    < Function < Object < null
Object   < Function < Object < null
Function < Function < Object < null

Here is proof.这是证据。 Below I am just asking for the prototype found for each object: Note: Object.prototype.toString.call() just tells us the string name of the prototype:下面我只是询问为每个对象找到的原型: 注意: Object.prototype.toString.call()只是告诉我们原型的字符串名称:

Object.prototype.toString.call(String);// [object Function]
Object.prototype.toString.call(Array);// [object Function]
Object.prototype.toString.call(Object);// [object Function]
Object.prototype.toString.call(Function);// [object Function]

Object.prototype.toString.call(String.__proto__);// [object Function]
Object.prototype.toString.call(Array.__proto__);// [object Function]
Object.prototype.toString.call(Object.__proto__);// [object Function]
Object.prototype.toString.call(Function.__proto__);// [object Function]

Object.prototype.toString.call(String.__proto__.__proto__);// [object Object]
Object.prototype.toString.call(Array.__proto__.__proto__);// [object Object]
Object.prototype.toString.call(Object.__proto__.__proto__);// [object Object]
Object.prototype.toString.call(Function.__proto__.__proto__);// [object Object]

Object.prototype.toString.call(String.__proto__.__proto__.__proto__);// [object Null]
Object.prototype.toString.call(Array.__proto__.__proto__.__proto__);// [object Null]
Object.prototype.toString.call(Object.__proto__.__proto__.__proto__);// [object Null]
Object.prototype.toString.call(Function.__proto__.__proto__.__proto__);// [object Null]

Please not that the string "[object Function]" is saying that the "prototype" or parent object for the type was "Function.prototype".请注意,字符串“[object Function]”表示该类型的“原型”或父对象是“Function.prototype”。 So it a representation of the underlying prototype parent objects assigned at each level.所以它代表了在每一层分配的底层原型父对象。 Now let's explain this in more depth...现在让我们更深入地解释一下......

A prototype in JavaScript is a word that means the following: JavaScript 中的原型是一个词,意思如下:

  • All Objects in JavaScript ultimately inherit from a series of prototypes or "base classes" that assign their various properties and features through inheritance. JavaScript 中的所有对象最终都继承自一系列原型或“基类”,这些原型或“基类”通过继承为其分配各种属性和特性。 This cascades down a tree to the child at the bottom.这会沿着树向下层叠到底部的孩子。 In JavaScript ALL OBJECTS ultimately inherit from the Object.prototype which is close to the top of that inheritance tree.在 JavaScript 中,ALL OBJECTS 最终继承自接近该继承树顶部的Object.prototype
  • The term "prototype" means a special object with properties and methods inherited by child objects术语“原型”是指具有子对象继承的属性和方法的特殊对象
  • "prototype" is also a special property given to all Objects in JavaScript that assigns a given object as the parent prototype to a child but also grants access to changing the prototype. “原型”也是 JavaScript 中所有对象的特殊属性,它将给定对象作为父原型分配给子对象,但也授予更改原型的权限。 It controls the actual prototype assigned to a child object, but also acts like a true Class Property in that you can use it to manipulate the prototype of a child object.它控制分配给子对象的实际原型,但也像真正的类属性一样,您可以使用它来操作子对象的原型。 I do not recommend you do this, but you can modify the original Object.prototype inherited by all object by adding new properties using a simple property addition or adding properties via a Object Literal containing properties:我不建议你这样做,但你可以修改所有对象继承的原始 Object.prototype ,方法是使用简单的属性添加添加新属性或通过包含属性的对象文字添加属性:
    Object.prototype.myproperty = "Hello World";
    Object.prototype.myobjectproperties = {text1: "Hello", text2: "World"};
  • "prototype" the property is expressed in combination with the Child Object name as "MyObjectType.prototype". “原型”属性与子对象名称组合表示为“MyObjectType.prototype”。 This new name is now both a identifier for the parent prototype and also a tool to change it.这个新名称现在既是父原型的标识符,也是更改它的工具。 But it is NOT a reference to the actual prototype object.但它不是对实际原型对象的引用。 (That is done below using __proto__). (这是在下面使用 __proto__ 完成的)。 It is assigned to all new objects when created of that type, It is first assigned to the function constructor that built the object.它在创建该类型时被分配给所有新对象,它首先被分配给构建该对象的函数构造函数。 then passed to the object the function constructor creates.然后传递给函数构造函数创建的对象。

  • "__proto__" is a reference to the actual prototype object assigned to the child. “__proto__”是对分配给子对象的实际原型对象的引用。 Its also a property but its a reference.它也是一个属性,但它是一个参考。 So its used to go up the tree of prototypes objects inherited by a child object and access them and their properties.因此,它用于在子对象继承的原型对象树上向上移动并访问它们及其属性。 This example below goes up the tree from an object literal created and ends at the top with "null":下面的示例从创建的对象字面量开始沿着树向上移动,并在顶部以“null”结束:

    alert({}.__proto__.__proto__);// null

Weirdness in Prototype原型中的怪异

So, in JavaScript inheritance, everything starts with a Function type?那么,在 JavaScript 继承中,一切都以 Function 类型开始? Why is that, Its because you cannot create any of the object "types" (Object, Array, Function, String. etc.) without a Function, And when you do.为什么会这样,因为你不能在没有函数的情况下创建任何对象“类型”(对象、数组、函数、字符串等),而当你这样做时。 they still get constructed from a "constructor" called somewhere in a function, A Function and its constructor is what not only creates new objects from types, but also assigns the "prototype" property, the "__proto__" property, and the actual tree of inherited prototypes or objects the child object will use.它们仍然是从函数中某处调用的“构造函数”构造的,函数及其构造函数不仅从类型创建新对象,而且还分配“原型”属性、“__proto__”属性和实际的树子对象将使用的继承原型或对象。

There are two states of objects in JavaScript, the "types" and the actual instantiated Objects. JavaScript 中的对象有两种状态,“类型”和实际实例化的对象。 That is why "Object" is not the same as a created Object as "const x = {}".这就是为什么“Object”与“const x = {}”创建的对象不同的原因。 And that is why the "type" starts out with a different inheritance or prototypes from its final one.这就是为什么“类型”以与其最终类型不同的继承或原型开始的原因。

Check this out!看一下这个!

// The Array type has a prototype of "Function.prototype"
alert(Object.prototype.toString.call(Array));// [object Function]

// But an instance of an Array object has a NEW prototype of "Array.prototype" that the function prototype's constructor created for the object!
const myarray = [];
alert(Object.prototype.toString.call(myarray));// [object Array]

So what happened?所以发生了什么事?

It turns out the FUNCTION CONSTRUCTOR creates and assigns the final prototype when the object is created.结果是 FUNCTION CONSTRUCTOR 在创建对象时创建并分配最终prototype But that custom prototype can be modified both before and after the array object is created with many more properties, objects, etc. So the final assigned prototype is set by the constructor of the Function object which as shown above was the Array types initial prototype.但是自定义原型可以在创建具有更多属性、对象等的数组对象之前和之后进行修改。因此最终分配的原型由 Function 对象的构造函数设置,如上所示是 Array 类型的初始原型。

So realize, the Function.prototype is the primary prototype of all Object types in JavaScript , It lies underneath all objects.所以要意识到, Function.prototype是 JavaScript 中所有对象类型的主要原型,它位于所有对象之下。 but is a tool to creating the final instantiated object that is assigned its own prototype when created.但它是一种创建最终实例化对象的工具,该对象在创建时被分配了自己的原型。 Note that the "Array.prototype" has a parent prototype of Object.prototype who has a parent of "null".请注意,“Array.prototype”的父原型为Object.prototype ,其父原型为“null”。 So the Object.prototype remains the top parent inherited by all these objects.所以Object.prototype仍然是所有这些对象继承的顶级父对象。 But in the creation of them the constructor changes the immediate parent of all child objects when new objects get created.但是在创建它们时,构造函数会在创建新对象时更改所有子对象的直接父对象。

Note that the Function.prototype gets many of its features from its own Object.prototype it too inherits.请注意, Function.prototype从它自己的 Object.prototype 中获得了许多特性,它也继承了它。 The prototype it builds for your created objects are also made from this parent prototype.它为您创建的对象构建的原型也是从这个父原型制作的。 So in the end.所以最后。 the Object.prototype provides the goodies needed for Function types and all types to get created and manage the prototype assigned to them. Object.prototype提供了创建函数类型和所有类型所需的好东西,并管理分配给它们的原型。 Just remember Function like Object is a special pre-built type with special tools and features needed to create all types of objects!请记住Function like Object是一种特殊的预构建类型,具有创建所有类型对象所需的特殊工具和功能!

Last test....lets see how prototype works for CUSTOM OBJECTS we create.上次测试....让我们看看原型如何为我们创建的自定义对象工作。 The example below proves that the function constructor (part of the Function.prototype ) assigns the "prototype" property to the created objects BUT can be customized with various properties and methods before or after being assigned to the objects prototype of MyCustomObject.prototype .下面的示例证明函数构造函数( Function.prototype的一部分)将“原型”属性分配给创建的对象,但可以在分配给MyCustomObject.prototype的对象原型之前之后使用各种属性和方法进行自定义。 This shows that the final prototype of your object need not be a static copy of the Object.prototype 's inherited properties, but can be something you create that is entirely new!这表明你的对象的最终原型不需要是Object.prototype的继承属性的静态副本,而可以是你创建的全新的东西!

let newPet;
function Pet() {
  this.fourlegs = true;
}

var Cat = {
  type : "cat"
}

var Dog = {
  type : "dog"
}

// We can see the prototype our constructor created for us
// and modify it as we like! Here we assigned it to an object
// which only means the prototype will merge "Cat" object's
// properties into the Pet.prototype.
Pet.prototype = Cat;

newPet = new Pet();
alert(newPet.type);// cat - inherited the Cat Object's properties in the prototype

Pet.prototype = Dog;

newPet = new Pet();
alert(newPet.type);// dog - inherited the Dog Object's properties in the prototype

alert(newPet.fourlegs);// true - this shows, even though you replace prototype, it ADDs the new types but does NOT erase the existing object properties! This must mean "prototype" is dynamically additive and rebuilt until the final "Pet" prototype is complete.

// Now change the "Pet.prototype" so all new objects have a new property.
Pet.prototype.furcolor = "white";
newPet = new Pet();
alert(newPet.furcolor);// "white"

// So you can see the "Pet.prototype" is dynamic, something you can tell the function constructor to modify!

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

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