简体   繁体   中英

Best way to retrieve the prototype of a JS object

Trying to understand Prototypes in 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

Object.prototype.__proto__ points to the object which was used as prototype when the object was instantiated.

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. 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). And prototype is not even available as a property of a , because you've created a totally empty object, so there's nothing.

Also notice that __proto__ is now deprecated .

Why? I don't know, but I have never used it so I don't care :)

prototype is a different thing, eg

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.

This is why you need prototype and you don't care about __proto__ in real life. If I'm wrong please show me useful usage of __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. If prototype property doesn't exist, there is no prototype of the JS object, even if sth was used in the process of instantiation.

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 .

Because obj is a Function object, it has a prototype property by default just in case it is to be used as a constructor.

In:

> obj.prototype.x = "a";

a new x property is added to obj.prototype that is assigned a value of the string 'a' . Note that obj only has a prototype property by default because it's a Function object.

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.

You can access a instance's internal [[Prototype]] using ES5 Object.getPrototypeOf , however it may not be supported everywhere.

You can also access a instance's internal [[Prototype]] using the non–standard __proto__ where supported.

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).

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.

So while obj.prototype has a clear standardized behav8our accross browsers, obj.__proto__ behaves differently in different browsers.

You're looking at this sideways...

.prototype and .__proto__ are the same object (or are at one specific point in time)...

BUUUUUT they're propertes of different objects.

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)

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.
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;

...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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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