19

It is often said that every Javascript object has a prototype property, but I find that foo.prototype has a value only if foo is a function.

On Chrome and Firefox, obj.__proto__ has a value -- is this the said prototype property? But on IE 9, it won't work (is there some way that can?), and I thought by prototype property, that means obj.prototype should work?

I understand that Object.getPrototypeOf(obj) seems to show this prototype property, but why need a special method to get it? Why not just like person.name, which is to get the name property of the person object?


Update: by the way, obj.constructor.prototype seems to sometimes be that prototype, but sometimes not, as in the following code done with Prototypal inheritance with no constructor: (this method is in the Pro Javascript Design Patterns book by Harmes and Diaz by Apress 2008, p. 46)

var Person = {
    name: 'default value',
    getName: function() {
        return this.name;
    }
}

var reader = clone(Person);
console.log(reader.getName());
reader.name = "Ang Lee";
console.log(reader.getName());

function clone(obj) {
    function F() {};
    F.prototype = obj;
    return new F;
}

console.log("the prototype of reader is", Object.getPrototypeOf(reader));

console.log(Object.getPrototypeOf(reader) === reader.constructor.prototype);
console.log(Object.getPrototypeOf(reader) == reader.constructor.prototype);

console.log(Object.getPrototypeOf(reader) === reader.__proto__);
console.log(Object.getPrototypeOf(reader) == reader.__proto__);

the result will show false, false, true, true for the last 4 lines.

nonopolarity
  • 146,324
  • 131
  • 460
  • 740
  • 2
    Objects are all related to a prototype, but not necessarily by a visible property. In other words, the JavaScript runtime internals know what the prototype object is, but it may not be possible for your code to determine what it is. As to *why* that is true, well, it's just the way that JavaScript was implemented. – Pointy Sep 30 '12 at 13:08
  • 2
    Anyone who says "every JavaScript object has a prototype property" is referring to the internal property (exposed as `__proto__` on most browsers, as you mentioned). – Dagg Nabbit Sep 30 '12 at 13:09
  • 1
    Take a look at this similar question: http://stackoverflow.com/questions/9451881/ – Dagg Nabbit Sep 30 '12 at 13:13

2 Answers2

19

Every JavaScript object has an internal "prototype" property, often called [[prototype]], which points to the object from which it directly inherits. This is exposed in FF and Chrome by the non-standard __proto__ property. Object.getPrototypeOf is a getter for this internal property.

Every JavaScript function [object] has a property prototype, which is initialized with an [nearly] empty object. When you create a new instance of this function by calling it as a constructor, the [[prototype]] of that new object will point to the constructor's prototype object.

If you get the [[prototype]] of a function (every function is an object, so it has one), it will result in the Function.prototype object from which functions inherit their methods (like bind, call, apply etc). See also Why functions prototype is chained repeatedly? on that.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • you mean with "nearly" empty object? how come you put in square bracket? – nonopolarity Sep 30 '12 at 13:26
  • 4
    The nearly empty object has a non-enumerable property `constructor` on it, which points to the constructor function. The notation with the double square-brackets comes from the [official EcmaScript specification](http://ecma-international.org/ecma-262/5.1/#sec-8.6.2) which uses this format for all internal properties. – Bergi Sep 30 '12 at 13:34
  • what about the "single" bracket notation such as yours? [nearly] empty – nonopolarity Sep 30 '12 at 13:49
  • That's just my personal style of [parenthesis](http://en.wikipedia.org/wiki/Parenthesis) - I often use square brackets for [single] words when omitting them does not change the meaning of the sentences, but could help understanding or is technically [more] correct. Not sure about official grammar rules regarding that, I'm no native English writer :-) – Bergi Sep 30 '12 at 14:52
  • @Bergi isn't there a `__proto__` property as well, in addition to the `constructor` property ? Also, this means that there is another internal `[[prototype]]` too. – doubleOrt Sep 08 '17 at 15:17
  • @Taurus No, there is no `__proto__`, that's just a deprecated inherited getter/setter. Of course, every prototype object does have a [[prototype]] from which it inherits. – Bergi Sep 08 '17 at 15:28
  • But if there were no `__proto__` then when trying to access it, you would get `undefined`. This is definitely not the case, try to compare `x.prototype.__proto__` with `Object.prototype`, it will evaluate to true; this would definitely not be the case if it were not there. – doubleOrt Sep 08 '17 at 15:31
  • @Taurus As I said, it's inherited. And it's deprecated, so don't spend much more thought on it. Use `Object.getPrototypeOf(x.prototype) == Object.prototype` instead – Bergi Sep 08 '17 at 15:32
  • Doesn't an inherited property count as a property anyways ? i am just curious. – doubleOrt Sep 08 '17 at 15:36
  • @Taurus Since we were discussing prototypes anyway, I had interpreted it to mean "own property". – Bergi Sep 08 '17 at 15:37
  • @Bergi Thanks. Now that we've come this far anyways, could i ask you a small question ? Why is `Object.prototype.__proto__` null ? Shouldn't it be equal to `Object.prototype` since `Object.prototype` is basically an instance of Object (created with an object literal), so its `__proto__` property should just be a reference to the prototype of the object it was created from, which is `Object` ? I am wrong but naturally i would expect `Object.prototype.__proto__ === Object.prototype` to evaluate to true. – doubleOrt Sep 08 '17 at 15:43
  • @Taurus No, a prototype is not "created from" its respective constructor, rather it is what *defines* an instance. And [[prototype]] chains must be linear, no circles or self-references are allowed - imagine what it would mean for the lookup mechanism. – Bergi Sep 08 '17 at 15:49
  • @bergi i am not saying a prototype is created from its constructor, i was saying that its __proto__ should link to the prototype of the constructor function the instance has been created from ? Is this statement incorrect? Sorry man but it is a bit hard explaining this in a comment. – doubleOrt Sep 08 '17 at 15:56
  • @Taurus Yes, but I'm saying that prototype objects are not *instances* at all. They are supposed to link their parent prototype, not themselves. – Bergi Sep 08 '17 at 15:58
  • By prototype, do you mean like `Object.prototype` ? If so, aren't those literally created with an object literal by JS automatically, and therefore, instances of `Object'. What i am saying is: isn't `Object.prototype` an instance of `Object` ? – doubleOrt Sep 08 '17 at 16:02
  • @Taurus I'm talking of all prototype objects, `x.prototype` and `Object.prototype` and every other one. No, they are created automatically, but not through an object literal. And see for yourself: `Object.prototype instanceof Object` or `x.prototype instanceof x` are both false (because `x.prototype.isPrototypeOf(x.prototype)` is as well, given that it inherits from `Object.prototype` *not from itself* - and `Object.prototype` doesn't inherit from itself neither, it inherits from nothing: `null`). – Bergi Sep 08 '17 at 22:20
  • @Bergi oh thanks! That is what i was talking about. So prototype objects aren't created using an object literal and Javascript does some behind-the-scenes magic to determine the `__proto__` of prototype objects. – doubleOrt Sep 09 '17 at 04:53
  • There are some special functions in JS which lack a `.prototype` property, I don't really remember which ones they were and neither MDN nor Google is helping, so I must resort to you again, which functions are those ? – doubleOrt Dec 25 '17 at 23:02
  • 1
    @Taurus Arrow functions, methods (of `class`es or as shorthands in object literals), and bound functions. – Bergi Dec 26 '17 at 08:53
  • @Bergi Thanks :) – doubleOrt Dec 26 '17 at 14:25
6

It is the constructor of every Object that has a prototype. So for some foo, baror foobar:

var foo = {};
console.log(foo.constructor.prototype); //=> Object
var bar = 5;
console.log(bar.constructor.prototype); //=> Number
function Foobar(){} 
var foobar = new Foobar; //Foobar used a constructor
console.log(foobar.constructor.prototype); //=> Foobar
KooiInc
  • 119,216
  • 31
  • 141
  • 177
  • aha, sometimes the constructor way won't work it seems, please see the update in the question – nonopolarity Sep 30 '12 at 13:24
  • @動靜能量 That's why you see people manually updating the constructor when they do prototypal inheritance... something like `(F.prototype = obj).constructor = F;` – Dagg Nabbit Sep 30 '12 at 13:45