3

I've read a lot of amazing articles and discussions (like this one) about prototype property of an object but there is a big question here. When we observe the behavior of "prototype" property we realize that it is actually another object. We can see it has its own proto and constructor properties just like an object.

var myobj= function(){};
myobj.prototype.constructor== myobj  --> true

So these are the questions :

  1. Is "prototype" itself an object?
  2. What is the relationship between prototype and the object it's related to (in this example myobj)?
  3. Why myobj.prototype.__proto__ is by default the "Object{ }" but its constructor is myobj?
  4. We know : "__proto__ is the actual object that is used in the lookup chain to resolve methods, etc. prototype is the object that is used to build __proto__ when you create an object with new". But we can see that this is not just what prototype does. I think : Prototype acts like a container object of all the shared methods and properties of an object! Then, when an instance of an object is created using new, its internal [[Prototype]] points to the prototype where the shared behaviors and properties of a class is exposed to the instances! Is this true?

In the end : It seems when we instantiate a class, the constructor of the instance is set to the constructor of the prototype of that object. Can this conclusion true?

var b= new myobj();
 b.constructor== myobj.prototype.constructor --> true
 b.constructor == myobj --> true
 myobj.prototype={};
 b.constructor == myobj  --> false
 b.constructor== Object --> true
 myobj.prototype.constructor== Object --> true
Community
  • 1
  • 1
Amir Jalilifard
  • 2,027
  • 5
  • 26
  • 38
  • 4
    #4 doesn't seem to be a question? It actually states the solution. – Bergi Jun 08 '15 at 16:51
  • 1
    To reduce potential confusion: Only **functions** have a `prototype` property, not *all* objects. `myobj` is a function. – Felix Kling Jun 08 '15 at 16:52
  • @ Bergi The rest of the question is "Prototype acts like a container object of all the shared methods and properties of an object! Then, when an instance of an object is created using new, its internal [[Prototype]] points to the prototype where the shared behaviors and properties of a class is exposed to the instances! Is this true?" but I couldn't do this because of text editor of stackoverflow – Amir Jalilifard Jun 08 '15 at 16:53
  • Yes, it's true. Although I don't see what the markdown syntax didn't let you do. – Bergi Jun 08 '15 at 16:56
  • @ Bergi The question was edited – Amir Jalilifard Jun 08 '15 at 16:57
  • Related: [JavaScript inheritance and the constructor property](http://stackoverflow.com/q/8093057/783743) – Aadit M Shah Jun 08 '15 at 16:59
  • @ Aadit Just a part of this question is related to this post. – Amir Jalilifard Jun 08 '15 at 17:01
  • 1
    Yes `prototype` is just an object. That's how prototypal inheritance work: Objects have an internal reference to another object, their prototype. What's the confusion about? I can't really make out the core of the question. Btw, `b.constructor == myobj //--> false` is incorrect. It's still `true` even after `myobj.prototype={};`. Are you confused about `constructor`? That's just a *predefined* property that every `prototype` object has. Do `console.dir(myobj.prototype)` and you'll see. – Felix Kling Jun 08 '15 at 17:02
  • The "It seems when we instantiate a class, the constructor of the instance is the constructor of the prototype of that object" part is confusing me. Prototypes are just that, and they are assigned to the instance that the constructor creates. You can access the prototype and invoke prototype methods without creating an instance via the constructor. – Jesse Kernaghan Jun 08 '15 at 17:04
  • @ Felix The "prototype" is an independent object that the function is related to this object. How the function is pointing to its "prototype" while myobj.__proto__== myobj.prototype is false. If we have to different object, how they are related to each other? Just this question is full of doubt and parts that can make huge confusions. Imagine we have an idependent object but unfortunately JS is showing this object as the property of a function! So, how JS relates function and its prototype? We know the only way is using the internal [Prototype]] but seems the other way around! – Amir Jalilifard Jun 08 '15 at 17:09
  • Wait what? `myobj.__proto__== myobj.prototype` is not true. Every function has a `__proto__` property since every function is an object. Functions also have a `prototype` property, which becomes the prototype of every instance created by the function if called with `new`. They are two different objects, they have two different purposes and there is no relation between them. This is all well explained in the question you linked to: http://stackoverflow.com/questions/9959727/proto-vs-prototype-in-javascript . – Felix Kling Jun 08 '15 at 17:12
  • @Felix Yes. I forgot to write myobj.__proto__== myobj.prototype is false. As you said "They are two different objects, they have two different purposes" but you said there is no relation between them. While there is. If there is no relation between them, how the prototype object can know which function it is related too? – Amir Jalilifard Jun 08 '15 at 17:16
  • 2
    "If there is no relation between them, how the prototype object can know which function it is related too" The prototype doesn't need to know which function it is assigned to, nor does it care. A prototype object can be assigned to an infinite number of constructors, there is no one to one relationship between them. – Jesse Kernaghan Jun 08 '15 at 17:28
  • @Jesse Kernaghan But it doesn't make sense, I have something like this : myobj.prototype.height="180". If the prototype doesn't need to know which function it is assigned to, why for example I don't have the "hight" property for another object e.g. myobj2 ? – Amir Jalilifard Jun 08 '15 at 17:34
  • @AmirJalilifard if `myobj` and `myobj2` have the same prototype, they will both have access to the `height` set in the prototype. If you don't explicitly assign the same object as a prototype to both, they will not share that prototype. – Jesse Kernaghan Jun 08 '15 at 17:38
  • @ Jesse Kernaghan Ok. Then the "prototype" object needs to know which function it is related to. And it accomplish this by setting it value as the name of that class. – Amir Jalilifard Jun 08 '15 at 17:44
  • @AmirJalilifard see the breakdown in my answer. The prototype doesn't need to know the constructor at all, the object instance does only for some simple things (like checking where it was instantiated via `instanceof`). – Jesse Kernaghan Jun 08 '15 at 18:30

2 Answers2

5
  1. Yes, the prototype object is an object. It is implicitly constructed together with the function.
  2. I wouldn't call that a "parent". Their only relation is that the myobj function does have a .prototype property with the prototype object as its value.
  3. The prototype object does inherit from Object.prototype. It does have an own .constructor property with the myobj function as its value. (It's really just a property)
  4. Yes, this is true. .__proto__ is a non-standard accessor to the internal [[Prototype]] field. As such, they are often used synonymous.
  5. No, when you construct an instance, no .constructor property is set. All that happens is the new instance inherits from the prototype object, and the prototype object has that constructor property. Notice that the myobj.prototype={}; in your example has no effects on your previously constructed instances.
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • The confusion is that : The "prototype" is an independent object that the function is related to this object. How the function is pointing to its "prototype" while myobj.__proto__== myobj.prototype. If we have to different object, how they are related to each other? Imagine we have an idependent object but unfortunately JS is showing this object as the property of a function! So, how JS relates function and its prototype? We know the only way is using the internal [Prototype]] but seems the other way around! – Amir Jalilifard Jun 08 '15 at 17:12
  • 1
    Yes, they are independent objects, referencing each other only via the `.prototype` and resp. `.constructor` properties. There is **no inheritance relationship** between them, `myobj.__proto__== myobj.prototype` is **false**. Instead, `myobj` is a function and inherits from `Function.prototype`, and `myobj.prototype` is a plain object that inherits from `Object.prototype`. – Bergi Jun 08 '15 at 17:21
  • Ok but if they are two different objects, how the prototype object can know which function it is related too? – Amir Jalilifard Jun 08 '15 at 17:25
  • As I said, it has a `.constructor` property with a function as its value. It doesn't need to know that at all, however. – Bergi Jun 08 '15 at 17:26
1

I know there is an accepted answer, but it seems there is some confusion as to what a prototype is, what a constructor function is, and how they interact.

Take this object for example:

var foo = {
  bar : 'hello',
  sayBar : function(){
    alert(this.bar);
  }
};

You can use it as it is, and as you would expect. You can reassign foo.bar and use the sayBar method without any issues:

foo.bar = 'Goodbye';
foo.sayBar(); //alerts(Goodbye);

Now say you need to have a bunch of objects that all need a bar property, but with different values. This is when you could create a constructor function to create unique instances:

var fooClass = function(newbar){
  this.bar = newbar;
};

Which can be invoked like so:

var myFoo = new fooClass('baz');
console.log(myFoo.bar); //logs 'baz'

Which can be broken down like this behind the scenes:

var fooClass = function(newbar){
  //**IF 'new' is declared ** create an instance object, for now it has no declared prototype other than Object's base prototype
  //That instance of the prototype is now scoped to 'this'

  //it sets the 'constructor' of the instance behind the scenes      
  //this.constuctor = [our constructor function]

  // now we can assign values to our instance and invoke it's methods

  this.bar = newbar;
  // our instance now has a key 'bar' that has the value of newbar


  // so our instance now looks like this:
  //
  // { 
  //  bar : [newbar]
  // }


  // return our instance object { bar : [newbar] }
};

This is where prototype objects come into play. Let's use our foo object as fooClass prototype:

var fooClass = function(newbar){
  this.bar = newbar;
};

fooClass.prototype = foo;

Now, as you'd expect, you can use foo's methods:

var myFoo = new fooClass('baz');
myFoo.sayBar(); //alerts baz

This is now what the constructor is doing:

var fooClass = function(newbar){
  //**IF 'new' is declared ** create an instance object, which uses foo as it's prototype
  //That instance of the prototype is now scoped to 'this'

  //it sets the 'constructor' of the instance behind the scenes      
  //this.constuctor = [our constructor function]

  // now we can assign values to our instance and invoke it's methods

  this.bar = newbar;
  // we have now overridden foo's default foo.bar with our instance bar


  // so our instance now looks like this:
  //
  // { 
  //  bar : [newbar], //overridden in constructor
  //
  //  //with access to foo's methods through the prototype chain
  //  sayBar : function(){
  //    alert(this.bar);
  //  }
  // }


  // return our instance object
};

There is nothing magical happening, all the constructor function is doing is creating and returning an object instance, and all .prototype = is doing is setting the prototype for that object.

What happens if I forget 'new'?

If you don't use new when using a constructor function, an new object instance is not created or returned. This why it's often checked to see if your current instance has the proper constructor:

var fooClass = function(newbar){
  if(!(this instanceof fooClass)){ //if this constructor != fooClass
    return new fooClass(newbar); //refire constructor with 'new'
  }

  //...
};
Jesse Kernaghan
  • 4,544
  • 2
  • 18
  • 25