Object.create(). How it works?


#1

I’m trying to understand how Object.create() works.

The argument of Object.create() is the object which should be the prototype of the newly-created object.

The following code works:

function Animal(name, numLegs) {
    this.name = name;
    this.numLegs = numLegs;
    this.isAlive = true;
}

function Penguin(name) {
    this.name = name;
    this.numLegs = 2;
}

function Emperor(name) {
    this.name = name;
    this.saying = "Waddle waddle";
}

// set up the prototype chain
Penguin.prototype = new Animal();
Emperor.prototype = new Penguin();

var myEmperor = new Emperor("Jules");

console.log(myEmperor.saying); //Prints "Waddle waddle"
console.log(myEmperor.numLegs);  //Prints 2
console.log(myEmperor.isAlive); //Prints true

I try to do the same thing with Object.create() but the last 2 commands print Undefined:

function Animal(name, numLegs) {
    this.name = name;
    this.numLegs = numLegs;
    this.isAlive = true;
}

function Penguin(name) {
    this.name = name;
    this.numLegs = 2;
}

function Emperor(name) {
    this.name = name;
    this.saying = "Waddle waddle";
}

// set up the prototype chain
Penguin.prototype = Object.create(Animal.prototype)
Penguin.prototype.constructor = Penguin

Emperor.prototype = Object.create(Penguin.prototype)
Emperor.prototype.constructor = Emperor

var myEmperor = new Emperor("Jules")

console.log(myEmperor.saying); //Prints "Waddle waddle"
console.log(myEmperor.numLegs);  // Prints Undefined
console.log(myEmperor.isAlive); // Should print true but prints Undefined

However, If I type Penguin.prototype = Object.create(Animal.prototype, { numLegs: { value: 2 } }) then console.log(myEmperor.numLegs); Prints 2.

I’m confused why do I have to redefine the numLegs property when it is already defined in the Penguin constructor?

I tried to copy the example from MDN:

//superclass
function Shape() {
  this.x = 0;
  this.y = 0;
}

// superclass method defined on it's prototype object
Shape.prototype.move = function(x, y) {
  this.x += x;
  this.y += y;
  console.info('Shape moved.');
};

// Another class called Rectangle
function Rectangle() {}

// Rectangle extends Shape
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;

var rect = new Rectangle();

console.log('Is rect an instance of Rectangle?',
  rect instanceof Rectangle); // true
console.log('Is rect an instance of Shape?',
  rect instanceof Shape); // true
rect.move(1, 1); // Outputs, 'Shape moved.'

#2

This line is in the MDN documentation:

Shape.call(this); // call super constructor.

and missing in your code, and its vital. In the MDN example it will call the Shape (super class) constructor.

you don’t have this, so your constructor Animal is never called, which is why this.name, thisnumLegs and this.isAlive are undefined, without a call to the constructor, these variables are never defined


#3

Okay. I am really confused in inheritance concept so I was just experimenting with Object.create(Animal.prototype) and new Animal() and they showed different results so I got even more confused…

Thanks mate :+1:


#4

Yea, Javascript uses prototype inheritance, which is indeed tricky.

thankfully, you are not the only one struggling with this:

https://stackoverflow.com/questions/4166616/understanding-the-difference-between-object-create-and-new-somefunction


#5

I’m starting to understand it now but having problems in inheriting methods from the prototype of the prototype object. Can’t see where I’m going wrong.

function Human() {
  this.eyes = 2;
  this.ears = 2;
  this.nose = 1;
  this.fingers = 18;
  this.thumbs = 4
  this.limbs = 4;
  this.thoughts = true;
}
Human.prototype.saying = function() {
 alert("I am no bird and no net ensnares me. I am a free human being with an independent will.")
}

function Person(first, last, age, gender, interests) {
  Human.call(this);
  this.first = first;
  this.last = last;
  this.age = age;
  this.gender = gender;
  this.interests = interests
}
Person.prototype.intro = function() {
  alert('Hi! I\'m ' + this.first + '. I am' +' '+ this.age +' '+ 'years old.');
};

var me = new Person("M", "19", 23, "male", ["Reading", "Coding", "Football"])

Person.prototype = Object.create(Human.prototype);
//Person.prototype.constructor = Person;

console.log(me.eyes)
console.log(me.interests)
console.log(me.gender)
console.log(me.nose)
console.log(me.constructor) //Prints Person when it should print Human because I haven't set the constructor property of the prototype to Person.
me.saying() //Doesn't work


#6

you made a mistake here:

var me = new Person("M", "19", 23, "male", ["Reading", "Coding", "Football"])

Person.prototype = Object.create(Human.prototype);

you create the instance first, and then set up inheritance. That doesn’t work

classes/objects are like blueprints. Lets do an example. Lets say we have a blueprint of a house (which represents a class/object in this analogy), and then we build a house (instance of class/object, me in your case) and then make changes to blueprint (Person.prototype = Object.create(Human.prototype);) the house we build already won’t change.

we can verify it as well, with code:

var me = new Person("M", "19", 23, "male", ["Reading", "Coding", "Football"])

Person.prototype = Object.create(Human.prototype);

console.log('Is me an instance of Human?',
  me instanceof Human); 
console.log('Is me an instance of Person?',
  me instanceof Person); 

#7

Yes. That’s a really good analogy. I was very confused when it came to linking classes with other classes and creating instances with them. Will remember. Thanks :+1:


#8

Did you figure it out now?


#9

I’m on my way…

I’m using Codepen and sometimes it runs and sometimes it doesn’t so sometimes it gets confusing.

For example, nothing happens when I write the following code and it has happened before also:

function Person(first, last, age, gender, interests) {
  //Human.call(this);
  this.first = first;
  this.last = last;
  this.age = age;
  this.gender = gender;
  this.interests = interests
}
Person.prototype.intro = function() {
  alert('Hi! I\'m ' + this.first + '. I am' +' '+ this.age +' '+ 'years old.');
};

Person.prototype.int = function() {
  var strt = 'I like '
  for(var i = 0; i < this.interests.length; i++) {
    strt+= interests[i] + ','
    if(i = this.interests.length-1) strt += 'and '+ interests[this.interests.length-1]
  }
  return strt
};

var me = new Person("M", "19", 23, "male", ["Reading", "Coding", "Football"])

console.log(me.int())
me.intro()





#10

i would use jsbin or jsfiddle, which have a run button which i thinks work better for console then codepen.

that is because you have an error here:

if(i = this.interests.length-1)

single equal signs means assign, is that really what you want to do here?


#11

Yea that I got. Codepen also has a run button but you have to disable the Auto-Updating Preview in settings.

I tried JSBin and I’m trying out others also…


#12

Okay, good. Anything you still need help with?


#13

Just trying to run my code…

I can’t find an editor which has a console in it. They all show the output (HTML + CSS + JS) but on Codepen and JSBin show console. But Codepen just isn’t running the code.

Will get back to you if anything happens. Thanks


#14

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.