Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript inheritance: calling Object.create when setting a prototype

I'm learning some aspects of Object-oriented Javascript. I came across this snippet

var Person = function(firstName, lastName)
{
  this.lastName = lastName;
  this.firstName = firstName;
};

Object.defineProperties(Person.prototype, {
  sayHi: {
    value: function() {
      return "Hi my name is " + this.firstName;
    }
  },
  fullName: {
    get: function() {
      return this.firstName + " " + this.lastName;
    }
  }
});

var Employee = function(firstName, lastName, position) {
  Person.call(this, firstName, lastName);
  this.position = position;
};

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

var john = new Employee("John", "Doe", "Dev");

And my question is: why does this snippet use Object.create(Person.prototype)? Shouldn't we simply reset prototype with:

Employee.prototype = Person.prototype;
like image 900
dragonfly Avatar asked Feb 23 '13 20:02

dragonfly


People also ask

How does JavaScript prototype inheritance work?

When it comes to inheritance, JavaScript only has one construct: objects. Each object has a private property which holds a link to another object called its prototype. That prototype object has a prototype of its own, and so on until an object is reached with null as its prototype.

Is JavaScript prototype inheritance?

The Prototypal Inheritance is a feature in javascript used to add methods and properties in objects. It is a method by which an object can inherit the properties and methods of another object. Traditionally, in order to get and set the [[Prototype]] of an object, we use Object. getPrototypeOf and Object.

How do you call the prototype property of a JavaScript object?

Using a constructor In JavaScript, all functions have a property named prototype . When you call a function as a constructor, this property is set as the prototype of the newly constructed object (by convention, in the property named __proto__ ).

How do you create an object with prototype?

Object. create() method is used to create a new object with the specified prototype object and properties. Object. create() method returns a new object with the specified prototype object and properties.


2 Answers

Doing Employee.prototype = Person.prototype is like saying "Employee is Person" rather than "Employee is a Person." Any changes to either prototype will be reflected in both classes.

Here's a demonstration. Obviously we don't want our Persons working because they don't have a position.

So the right way to setup the prototype chain without Object.create is:

Employee.prototype = new Person;

But this requires instantiating an object, which is a little funky -- especially if you don't want Person's constructor to be called. All of your Employee instances are going to inherit undefined "firstName" and "lastName" properties, regardless of whether you wanted that.

In this case it's no big deal -- the Employee constructor is going to set those properties on itself which will supersede the properties inherited from Person. But consider this example. One might think that freeTime is an instance level property for Person that will not be copied because it's not on the prototype. Plus, we never called the Person constructor from Employee. Not so -- freeTime was set on the Employee prototype because we had to instantiate an object.

So the best and cleanest inheritance you can do is through Object.create. If you want to call the parent class' constructor, you can do so explicitly from within the subclass' constructor. Another nice thing is that Object.create has a second (optional) argument to defineProperties. So you can also do this:

Employee.prototype = Object.create(Person.prototype, {
  work: {
    value: function() {
      return this.fullName+" is doing some "+this.position+" stuff");  
    }
  }
});

Of course, if you have to support legacy browsers you can't use Object.create. The alternative is to use clone / extend from libraries like underscore or lodash. Or there's this little dance:

var subclass = function() { };
subclass.prototype = Person.prototype;
Employee.prototype = new subclass;
like image 179
12 revs Avatar answered Nov 15 '22 16:11

12 revs


My guess is that the intent is to create a new object rather than just a reference from Person.

//create a new object with its prototype assigned to Person.prototype
Employee.prototype = Object.create(Person.prototype);
like image 40
james emanon Avatar answered Nov 15 '22 17:11

james emanon