简体   繁体   English

检索JS对象原型的最佳方法

[英]Best way to retrieve the prototype of a JS object

Trying to understand Prototypes in Javascript. 试图了解Javascript中的原型。 For this example: 对于此示例:

var obj = new Function();
obj.prototype.x = "a";

Why do I get different results from 为什么我从中得到不同的结果

console.log(obj.__proto__);

and

console.log(obj.prototype);

Thanks 谢谢

According to this source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype 根据此来源: https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype

Object.prototype.__proto__ points to the object which was used as prototype when the object was instantiated. Object.prototype.__proto__指向在实例化对象时用作原型的对象。

It simply means that object used as prototype to create Function object was empty function, and that's why you have function Empty() {} in the output. 这仅表示用作创建Function对象的原型的对象是空函数,这就是为什么在输出中有function Empty() {}的原因。 You can observe it here: 您可以在这里观察它:

console.log(Function.prototype);
var func = new Function();
console.log(func.__proto__);
console.log(func.prototype);
// OUTPUT:
// function Empty() {}
// function Empty() {}
// Object {} 

__proto__ of an empty object (eg var a = {} ) is Object {} because this is, what was used to create base of your object (in other words Object.prototype was used). __proto__一个空对象(例如var a = {}Object {}因为这是,什么被用来创建对象的基(换句话说Object.prototype被使用)。 And prototype is not even available as a property of a , because you've created a totally empty object, so there's nothing. 而且prototype甚至不能作为的属性a ,因为您已经创建了一个完全空的对象,因此没有任何东西。

Also notice that __proto__ is now deprecated . 另请注意, __proto__现在已弃用

Why? 为什么? I don't know, but I have never used it so I don't care :) 我不知道,但是我从未用过,所以我不在乎:)

prototype is a different thing, eg prototype是另一回事,例如

Changes to the Object prototype object are propagated to all objects unless the properties and methods subject to those changes are overridden further along the prototype chain. Object prototype object更改将传播到所有对象,除非经受这些更改的属性和方法沿原型链进一步被覆盖。

This is why you need prototype and you don't care about __proto__ in real life. 这就是为什么您需要prototype并且在现实生活中不关心__proto__ If I'm wrong please show me useful usage of __proto__ . 如果我写错了,请告诉我__proto__有用用法。

Hope it's clearer now. 希望现在更清楚。 And to answer your original question: 并回答您的原始问题:

Prototype of a JS object can be retrieved only by using prototype property, as __proto__ contains sth different. 只能通过使用prototype属性来检索JS对象的prototype ,因为__proto__包含其他内容。 If prototype property doesn't exist, there is no prototype of the JS object, even if sth was used in the process of instantiation. 如果不存在prototype属性,那么即使在实例化过程中使用了sth,也不会存在JS对象的原型。

In: 在:

> var obj = new Function();

a new function object is created whose internal [[Prototype]] (or __proto__ in browsers that support it) references Function.prototype , ie the built–in Function constructor's public prototype and assigned to the variable obj . 创建一个新的函数对象,该对象的内部[[Prototype]] (或支持它的浏览器中的__proto__ )引用Function.prototype ,即内置Function构造函数的公共原型,并分配给变量obj

Because obj is a Function object, it has a prototype property by default just in case it is to be used as a constructor. 因为obj是一个Function对象,所以默认情况下它具有prototype属性,以防万一它被用作构造函数。

In: 在:

> obj.prototype.x = "a";

a new x property is added to obj.prototype that is assigned a value of the string 'a' . 新的x属性将添加到obj.prototype中 ,该属性被分配了字符串'a' Note that obj only has a prototype property by default because it's a Function object. 请注意,默认情况下, obj仅具有prototype属性,因为它是Function对象。

So: 所以:

obj.prototype === obj.__proto__

is essentially: 本质上是:

obj.prototype === Function.prototype

which is clearly false. 这显然是错误的。

So to answer the question "Best way to retrieve the prototype of a JS object" then you can access a constructor's public prototype through its prototype property. 因此,要回答“检索JS对象原型的最佳方法”的问题,则可以通过其原型属性访问构造函数的公共原型。

You can access a instance's internal [[Prototype]] using ES5 Object.getPrototypeOf , however it may not be supported everywhere. 您可以使用ES5 Object.getPrototypeOf来访问实例的内部[[Prototype]] ,但是可能并非在所有地方都支持该实例。

You can also access a instance's internal [[Prototype]] using the non–standard __proto__ where supported. 您还可以使用受支持的非标准__proto__来访问实例的内部[[Prototype]]

A more general solution is to keep a reference to the constructor's prototype at the time the instance is created (since changing the constructor's prototype at some later stage will not change the [[Prototype]] of instances that have already been created). 更为通用的解决方案是在创建实例时保留对构造函数原型的引用(因为在以后的某个阶段更改构造函数的原型不会更改已经创建的实例的[[Prototype]] )。

So in a general case you might do: 因此,在一般情况下,您可以这样做:

function Foo() {
  this.internalProto = Foo.prototype;
}

var foo = new Foo();

// ES5, where supported
Object.getPrototypeof(foo) == Foo.prototype; // true

foo.internalProto == Foo.prototype; // true

// Non–standard, Where supported
foo.internalProto == foo.__proto__;     // true

Accordint to the MDN , obj.__proto__ has not been standardized. 根据MDN ,obj .__ proto__尚未标准化。

So while obj.prototype has a clear standardized behav8our accross browsers, obj.__proto__ behaves differently in different browsers. 因此,尽管obj.prototype在所有浏览器中都有明确的标准化行为,但obj .__ proto__在不同浏览器中的行为有所不同。

You're looking at this sideways... 您正在横向看...

.prototype and .__proto__ are the same object (or are at one specific point in time)... .prototype.__proto__是同一对象(或在某个特定时间点)...

BUUUUUT they're propertes of different objects. BUUUUUT它们是不同对象的属性。

var Human = function (name) {
    this.num_eyes = 2;
    this.num_heads = 1;
    this.name = name;
};
Human.prototype.die = function () { this.isAlive = false; };

var herman = new Human("Herman");

herman.__proto__.die === Human.prototype.die; // true

.__proto__ is a link to the CONSTRUCTOR .prototype (and typically, is the SAME object) .__proto__是指向CONSTRUCTOR .prototype的链接(通常是SAME对象)

It's almost like this: 几乎是这样的:

var Human = function () {
    this = {};
    this.num_eyes = 2;
    // ......
    this.__proto__ = Human.prototype;
};

That isn't exactly how constructors work, but really, that's the idea. 那不是构造函数的确切工作方式,但实际上就是这个想法。
And that's why .__proto__ and .prototype aren't the same thing. 这就是为什么.__proto__.prototype不是同一回事。
Because you're looking in the wrong place. 因为您找错了地方。

So if: 因此,如果:

var herman = new Human();
herman.__proto__ === Human.prototype;
var Human = new Function ();

...so logic then states that Human.__proto__ === Function.prototype; ...因此逻辑规定Human.__proto__ === Function.prototype;

...and if Human and Function aren't the same object, then their .prototype properties aren't going to be the same (unless you overwrite one with the other Human.prototype = Function.prototype; Human.__proto__ === Human.prototype; //true ...并且如果HumanFunction不是同一对象,则它们的.prototype属性将不会相同(除非您用另一个Human.prototype = Function.prototype; Human.__proto__ === Human.prototype; //true

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

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