69

I'm fairly new to the concept of JavaScript's prototype concept.

Considering the following code :

var x = function func(){
}

x.prototype.log = function() {
  console.log("1");
}

var b = new x();

As I understand it, b.log() should return 1 since x is its prototype. But why is the property b.prototype undefined?

Isn't b.prototype supposed to return the reference to the x function?

Mike
  • 14,010
  • 29
  • 101
  • 161
Pascal Paradis
  • 4,275
  • 5
  • 37
  • 50
  • 4
    No, `b.prototype` is _not_ supposed to be `x`. That's simply not how prototypes work in JavaScript. Are you thinking of the `__proto__` property? http://stackoverflow.com/q/572897/139010 – Matt Ball Jan 22 '13 at 02:46

5 Answers5

82

Only constructor functions have prototypes. Since x is a constructor function, x has a prototype.

b is not a constructor function. Hence, it does not have a prototype.

If you want to get a reference to the function that constructed b (in this case, x), you can use

b.constructor
Peter Olson
  • 139,199
  • 49
  • 202
  • 242
  • Peter, do you have a recommendation as to what book/online resource to read about all of the JS object model? – Victor Pudeyev Mar 28 '14 at 19:15
  • @VictorPiousbox The most precise and detailed source is the [ECMAScript specification](http://es5.github.io/) but it might be hard to read if you're not used to reading that sort of thing. Beyond that, I would just search for information using a search engine. – Peter Olson Mar 28 '14 at 19:30
  • After reading so many articles saying every object has prototype, I considered even objects created from function(using new) have one! But now I got it. – Pawan Jul 07 '15 at 05:37
  • https://www.w3schools.com/js/js_object_prototypes.asp says "Every JavaScript object has a prototype. The prototype is also an object." which contradiction of your answer where you says Only constructor functions have prototypes – ashwintastic Jul 17 '17 at 08:12
25

The .prototype property of a function is just there to set up inheritance on the new object when the function is invoked as a constructor.

When the new object is created, it gets its internal [[Prototype]] property set to the object that the function's .prototype property points to.

The object itself doesn't get a .prototype property. Its relationship to the object is completely internal.

That's why it works to do b.log(). When the JS engine sees that the b object itself has no log property, it tries to look it up on the objects internal [[Prototype]] object, where it successfully finds it.

To be clear, the [[Prototype]] property is not directly accessible. It's an internal property that is only indirectly mutable via other constructs provided by the JS engine.

the system
  • 9,244
  • 40
  • 46
15

All ordinary objects in JavaScript have an internal prototype slot (note: the prototype here does not refer to the prototype property). The ECMAScript standard (http://www.ecma-international.org/ecma-262/6.0/index.html) specifies that this slot is referred to as [[Prototype]]. You could access this slot through the __proto__ property.

__proto__ may not be reliably available across browsers. __proto__ becomes an official property in ECMAScript 6

The prototype property is, however, a property on a constructor function that sets what will become the __proto__ property on the constructed object.

You can access the prototype property of certain types, e.g., the core JavaScript types (Date, Array, and etc). Also a JavaScript function (, which can be regarded as a constructor) has a public prototype property. However, instances of a function do not have a prototype property.

In you case, var b = new x();, b is an instance of function x. Thus b.prototype is undefined. However, b does have an internal [[Prototype]] slot. If you output b.__proto__ in Google Chrome e.g., version 63.0.3239.132, or Firefox such as version 43.0.4

console.log(b.__proto__);

You will see its [[Prototype]] slot as below:

{log: ƒ, constructor: ƒ}

That's it.


And just for your reference, the whole code snippet is put as below:

var x = function() {
};
x.prototype.log = function() {
  console.log("1");
}

var b = new x();
b.log();  // 1

console.log(b.prototype); // undefined
console.log(b.__proto__); // {log: ƒ, constructor: ƒ}
console.log(x.prototype); // {log: ƒ, constructor: ƒ}
Yuci
  • 27,235
  • 10
  • 114
  • 113
  • constructor is hidden property by default. am i right. – Atul Jul 25 '18 at 07:17
  • @Atul, not sure if you meant Object.prototype.constructor. The constructor property returns a reference to the Object constructor function that created the instance object. You can access it, e.g., `var c = new x.prototype.constructor();` or `var d = new b.__proto__.constructor();` – Yuci Jul 25 '18 at 07:45
14

Before going through your code I want to make sure some concept of prototype that are required to understand your code behavior.

  1. [[prototype]] is a hidden property of a JavaScript object.This hidden property is nothing but a link to Object.prototype(If created by object literals).There is no standard way to access this [[prototype]] property.
  2. Functions in JavaScript are objects so they also have [[prototype]] property.Here, In case of function this hidden property is a link to Function.prototype.There is also no standard way to access this [[prototype]] property.
  3. Apart from this hidden link [[prototype]], Whenever a function object is created,a prototype property is created within it, which is separate from hidden [[prototype]] property.

Now coming to your code :

var x = function func(){}

When this line execute , a function object x is created with two links :

  • Function.prototype (not accessible),
  • x.prototype (accessible).

x.prototype.log = function() { console.log("1"); }

as we know now that x is a function object so x.prototype is accessible, so here you are able to include log method with it.

var b = new x();

b is an object but not function object .It has that hidden link [[prototype]] but It is not accessible. so when you try to access like b.prototype it gives undefined as a result.If you want to check the prototype of b than you can see (x.prototype).isPrototypeOf(b); it will return true. so you can say that hidden link is referenced to x.prototype.

Here are some facts about prototype :

  1. If object O is created with O = new func(){} then O[[prototype]] is Function.prototype.
  2. If object O is created with O = {}then O[[prototype]] is Object.prototype.
  3. If object O is created with O = Object.create(obj) then O[[prototype]] is obj.
Piyush Balapure
  • 1,023
  • 9
  • 14
Anshul
  • 9,312
  • 11
  • 57
  • 74
1

Because prototype is a property of functions (actually, constructors), since it defines the properties/methods of objects of this class (those which were created from the constructor this prototype belongs). Take a look at this link

Danilo Valente
  • 11,270
  • 8
  • 53
  • 67