0

I´m learning javascript OOP and I´m having issues understanding inheritance. Could you explain me why the outcomes from this two codes differ? :

Code 1

function a(){}

function b(){
    this.uno = "hello"}

b.prototype = new a();

function c(){
    this.dos = "bye"}

c.prototype= new b();

var obj = new c();

console.log(obj.uno);
console.log(obj.dos);
console.log(obj.constructor);

Output 1

hello 
bye
[function: a]

Code 2

function a(){}


function b(){
    this.uno = "hola"}


b.prototype = new a();


function c(){
    this.dos = "bye"}

c.prototype = {constructor:b}

var obj = new c();

console.log(obj.uno);
console.log(obj.dos);
console.log(obj.constructor);

Ouput 2

undefined
bye
[function: b]

I truly appreciate any guide on the subject.

Danny Buonocore
  • 3,731
  • 3
  • 24
  • 46
max fraguas
  • 438
  • 1
  • 6
  • 12
  • 1
    It differs because `new b()` does not return `{constructor:b}`, so it's not the same thing – adeneo Aug 09 '16 at 19:19
  • 1
    The question is: why exactly did you expect them to behave identically? They are clearly different. – Oriol Aug 09 '16 at 19:23
  • even if you assign an object to its own prototoype it doesnt make sense. – Redu Aug 09 '16 at 19:32
  • 1
    One of my previous answers on similar topic is http://stackoverflow.com/a/38819813/5102631. It also illustrates a similar kind of problem. @max you can check it too. – Ayan Aug 09 '16 at 19:41
  • The `constructor` property doesn't have any effect on prototypal inheritance in Javascript, unless your code uses it explicitly. This [question/answer](http://stackoverflow.com/q/4012998/6445533) might help. –  Aug 09 '16 at 19:56
  • Thank you all for your rapid answers, I'll study the posted links to get a better understanding on the subject. Obviously, I still have much to read. – max fraguas Aug 09 '16 at 22:48

2 Answers2

0

In the code snippet

function a() {}

function b() {
  this.uno = "hello"
}

b.prototype = new a();

function c() {
  this.dos = "bye"
}

c.prototype = new b();

var obj = new c();

console.log(obj.uno);
console.log(obj.dos);
console.log(obj.constructor);

Lets understand whats happening. When you are doing

b.prototype = new a();

A new instance of a is created and is directly assigned to prototype of b. So right at this moment if one does var obj = new b(); The obj.uno will be equal to hello.

Now, when the statement

c.prototype = new b();

is executed, the obj(a instance of the b class) is now assigned to the prototype of c. So right at this moment if one does var obj = new c();

  • obj.dos = bye as its assigned in the c constructor class.
  • obj.uno = 'hello' as it was once assinged while instanciating b constructor.
  • As the constructor property is not re-assigned it will still point to the original parent a. So obj.constructor = function a().

In the second snippet

function a() {}


function b() {
  this.uno = "hola"
}


b.prototype = new a();


function c() {
  this.dos = "bye"
}

c.prototype = {
  constructor: b
}

var obj = new c();

console.log(obj.uno);
console.log(obj.dos);
console.log(obj.constructor);

c.prototype = { constructor: b }

is not inheriting b or its prototype chain. In every constructors prototype chain there is aconstructorproperty which points to the constructor class. In the avobe statement, it just reassings it to the functionb`.

UPDATE: Constructor is a property defined in the prototype chain in any object and as functions are first-class-objects in JS, they too have this property inscribed.

So when you execute the above line, its basically changing the c.prototype.constructor value. And nothing else.

Had you been doing this

 c.prototype = {
  constructor: 5
}
...
console.log(obj.constructor); // 5.
//Its like setting a value for a property in a JS object.

So when you do:

console.log(obj.constructor);

It points to the newly assigned constructor, i.e. function b().

But as there is no inheritance,

console.log(obj.uno);

is definitely undefined.

However,

console.log(obj.dos);

will be bye when you are creating a new instance of the function c:

var obj = new c();

Hope this helps to understand JS prototypal inheritance in a better way.

Community
  • 1
  • 1
Ayan
  • 2,300
  • 1
  • 13
  • 28
  • Thank you very much for your dedicated answer Ayan. I thought the property "constructor" of the prototype object, was responsible for the inheritance of the function class. So, what do you meant when you said that **c.prototype = { constructor: b }** is not inheriting but reassigning? – max fraguas Aug 09 '16 at 22:45
  • Hey @maxfraguas Have updated that part of the answer, giving an example for it. Let me know if it sounds better – Ayan Aug 09 '16 at 23:02
-1

Because new b() !== {constructor:b} (as adeneo mentioned). The prototype expects a lot more than just a {constructor} property, so just providing an object (literal) with that won't do much.

Community
  • 1
  • 1
ssube
  • 47,010
  • 7
  • 103
  • 140