2

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

Amc_rtty
  • 3,662
  • 11
  • 48
  • 73
  • proto==contructor.prototype – dandavis Jan 15 '14 at 23:39
  • possible duplicate of [What does this sentence mean: "In other words, obj.prototype is in general not the obj's {Prototype}."](http://stackoverflow.com/questions/21075114/what-does-this-sentence-mean-in-other-words-obj-prototype-is-in-general-not-t), [Why this behaviour?__proto__ vs prototype?](http://stackoverflow.com/q/16394709/1048572) and mostly [__proto__ Vs. prototype in JavaScript](http://stackoverflow.com/q/9959727/1048572) – Bergi Jan 15 '14 at 23:41

4 Answers4

2

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 (e.g. 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, e.g.

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.

Karol
  • 7,803
  • 9
  • 49
  • 67
  • 1
    I believe `__proto__` is deprecated because it was never standardized, and has a replacement which is part of the standard: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf – Paul Jan 16 '14 at 00:25
  • You're right - just checked it - it's doing the same as `__proto__` but it's standarized: `var func = new Function(); console.log(func.__proto__); console.log(Object.getPrototypeOf(func)); console.log(func.prototype);` – Karol Jan 16 '14 at 00:29
2

In:

> var obj = new Function();

a new function object is created whose internal [[Prototype]] (or __proto__ in browsers that support it) references Function.prototype, i.e. 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
RobG
  • 142,382
  • 31
  • 172
  • 209
0

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.

JoshWillik
  • 2,624
  • 21
  • 38
  • 1
    Yes, but it doesn't answer the question, i.e. why `fnObj.prototype !== fnObj[[Prototype]]`. – RobG Jan 16 '14 at 01:14
0

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

Norguard
  • 26,167
  • 5
  • 41
  • 49