Difference between creating inheritance using object.create and new operator - javascript

Please find my two methods of creating inheritance. Can some one explain me what going on with each type.
Method 1:
function Person(name){
this.name = name;
}
Person.prototype.getName = function(){
return this.name;
}
function Employee(name, designation){
Person.call(this, name);
this.designation = designation;
}
Employee.prototype = new Person();
Employee.prototype.constructor = Employee;
Employee.prototype.getDesignation = function(){
return this.designation;
}
new Employee("Jagadish", "Cons");
Method 2:
function Person(name){
this.name = name;
}
Person.prototype.getName = function(){
return this.name;
}
function Employee(name, designation){
Person.call(this, name);
this. designation = designation;
}
Employee.prototype = Object.create(Person.prototype);
Employee.prototype.constructor = Employee;
Employee.prototype.getDesignation = function(){
return this.designation;
}
new Employee("Jagadish", "Cons");
I have inserted the images of console of each object. In first method i can see name property in Person class which is undefined (refer first screenshot).
But in case of second method of inheritance i dont have name property in Person class.
Can someone explain in depth about this behavior and what is happening in background.

There is nothing magical going on here, the program is doing exactly what it is told to do.
When you are calling new Person, you are creating a new object. That object has a name property because you are explicitly assigning to this.name inside the function.
Object.create however creates an empty object, unless it is passed a second argument with property descriptors.
To explain the specific difference between Object.create and new A:
new A():
Create a new object inheriting from A.prototype
Apply A to the new object, i.e. call A.call(newObj)
Object.create(A.prototype):
Create a new object inheriting from A.prototype
So you see, the specific difference between those two calls is that with new the function is applied to the new object, with Object.create is isn't.
Related: Benefits of using `Object.create` for inheritance

Related

Using .prototype for adding method to variable

I'm looking to analyze this code and I'm having some trouble. My trouble starts with this line. Customer.prototype = new Person();. Now as far as i'm aware. We can add some methods to our variables like we did with Person.prototype.getName. Great, now Person has a proto pointed towards a function that returns a name. So what does it mean when we do Customer.prototype = new Person();. Does this mean that take all the methods and statements in Person and put them inside the variable Customer?
var Person = function(name) {
this.name = name;
};
Person.prototype.getName = function() {
return this.name;
};
var john = new Person("John");
//Try the getter
alert(john.getName());
Person.prototype.sayMyName = function() {
alert('Hello, my name is ' + this.getName());
};
john.sayMyName();
var Customer = function(name) {
this.name = name;
};
Customer.prototype = new Person();
var myCustomer = new Customer('Dream Inc.');
myCustomer.sayMyName();
Customer.prototype.setAmountDue = function(amountDue) {
this.amountDue = amountDue;
};
Customer.prototype.getAmountDue = function() {
return this.amountDue;
};
myCustomer.setAmountDue(2000);
alert(myCustomer.getAmountDue());
Every object has a prototype, which is also an object.
When you do
Customer.prototype = new Person();
... you set the Customer's prototype object. The methods and properties do not get copied into a Customer object, but when you reference a property/method on a Customer, the prototype chain is followed to find that property/method.
In the case of myCustomer.sayMyName, the JavaScript engine first looks in myCustomer's owned properties, then in its prototype, which is a Person object, and then finally in the prototype of Person which is an object that has that method:
Person.prototype.sayMyName = function() {
alert('Hello, my name is ' + this.getName());
};
By doing Customer.prototype = new Person() we are essentially doing class-inheritance as in another language. So, say we had:
var p = new Person();
Customer.prototype = p;
var c = new Customer();
The prototype (__proto__) of c is p and the prototype of p is Person.prototype.
The naive way to do inheritance would be to Customer.prototype = Person.prototype which would make all instances of Customer share the same methods as Person. But, if we did Customer.prototype.newMethod = ..., it would also modify the prototype of Person.prototype (as they are the same object.
To allow a distinction between Customer prototype and Person prototype, we use new Person() instead as an intermediate in the chain which still has a link to the prototype of Person but is a separate object.
Note: Usually it is more conventional to do Customer.prototype = Object.create(Person) followed by Customer.prototype.constructor = Customer; because doing new Person() means that the constructor of Person is called (which is usually not wanted unless you are actually making a real object).

Javascript inheritance (through Backbone source code), why Surrogate function in Backbone?

Usual way to implement inheritance in javascript is something like:
function Person(name, surname) {
this.name = name;
this.surname = surname;
}
Person.prototype.whoAmI = function() {
console.log("I'am " + this.name + " " + this.surname);
}
function Ninja() {
Person.apply(this, arguments); // call to parent constructor
}
Ninja.prototype = new Person();
Ninja.prototype.constructor = Ninja;
var ninja = new Ninja("John", "Doe");
ninja.whoAmI();
From backbone what i can see is use of "Surrogate" function like: (very simplified example of what i can extract like example from Backbone source code)
function Person(name, surname) {
this.name = name;
this.surname = surname;
}
Person.prototype.whoAmI = function() {
console.log("I'am " + this.name + " " + this.surname);
}
function Ninja() {
Person.apply(this, arguments);
}
var Surrogate = function() { this.constructor = Ninja; }
Surrogate.prototype = Person.prototype;
Ninja.prototype = new Surrogate();
var ninja = new Ninja("John", "Doe");
ninja.whoAmI();
From what i can understand, these examples work exactly same so why need for Surrogate function.
I find one comment in the source about this:
Set the prototype chain to inherit from parent, without calling
parent's constructor function.
Why not calling parent constructor function?
Why not calling parent constructor function?
Because we want to constructor function to be only called when an instance is created. The Ninja.prototype however is not an instance of Person, it should not have name or surname properties - it should only inherit the whoAmI method. See also What is the reason to use the 'new' keyword at Derived.prototype = new Base for details.
Usual way to implement inheritance in javascript is something like
Only "something like". The correct way is not to call the parent constructor, but we don't need that Surrogate thingy for that. The standard is just to use Object.create:
Ninja.prototype = Object.create(Person.prototype);
Ninja.prototype.constructor = Ninja;
(for compatibility with ES3 environments just shim Object.create instead of littering your source code with Surrogate functions)

Javascript Prototype Inheritance and Chaining Constructs for an Object

When reading https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call for the section "Using call to chain constructors for an object":
function Product(name, price) {
this.name = name;
this.price = price;
if (price < 0)
throw RangeError('Cannot create product "' + name + '" with a negative price');
return this;
}
function Food(name, price) {
Product.call(this, name, price);
this.category = 'food';
}
Food.prototype = Object.create(Product.prototype);
function Toy(name, price) {
Product.call(this, name, price);
this.category = 'toy';
}
Toy.prototype = Object.create(Product.prototype);
var cheese = new Food('feta', 5);
var fun = new Toy('robot', 40);
I have read that a object's prototype is actually a object itself that points to the constructor's properties memory locations.
In function Food(name, price) it inherits the constructor's Product's properties with Product.call(this). What is Food.prototype = Object.create(Product.prototype); doing? Is it adding another prototype to Food(if that is even possible to have 2 prototypes)? Or is it appending to Food's prototype with the same prototype values of Product(which it already inherited so doesn't make sense to me ether)?
The essence of the problem cam be summarized as "why would you need to set prototypes at all"? In other words, why this is not sufficient to call the base class constructor and not to set the prototype?
The trick is that you could possibly not set the child class function's prototype! Your trivial example would work fine without it. Comment out the line and you will find that the code works with and without this line:
Food.prototype = Object.create(Product.prototype);
This is because all your object properties are set in constructors and by chaining constructors (calling the base class constructor) you have all the properties set on child class instances.
Consider however this:
function Base() {
this.BaseClassMethod = function() {}
}
vs
function Base() {
}
Base.prototype.BaseClassMethod = function() {}
As you can see, there are no fields but a method. Semantically, both snippets define a constructor function that creates instances having the sole BaseClassMethod method. However, in the first snippet there is a new extra function created for each created instance of the class, while in the second snippet the method definition is shared.
This very simple example shows that the same semantics can be achieved in different ways that have different profiles - in the above example is was at least the different memory footprint.
Yet another difference between these two is that in the latter, the function can be redefined somewhere in the future and the new version affects all previously created instances while in the first snippet what you can do is to change the definition in specific instances but not easily "in all previously created instances".
Whether or not this is your goal is another story. You can freely choose between these two ways of assigning methods to classes.
And there lies the answer to your question: without setting the prototype chain, methods defined in base class prototype (the latter snippet) would not be inherited if you only called the base class constructor from the child class constructor.
In other words, calling both the base class constructor and setting the prototype chain makes your inheritance independent on the way methods are defined in the base class.
Let's let code speak for itself. Object.create basically does this:
Object.create = function (o) {
//Object.create equals an anonymous function that accepts one parameter, 'o'.
function F() {};
//Create a new function called 'F' which is just an empty object.
F.prototype = o;
//the prototype of the 'F' function should point to the
//parameter of the anonymous function.
return new F();
//create a new constructor function based off of the 'F' function.
};
Hope this helps. Cheers
Food.prototype = Object.create(Product.prototype) is like extends in other languages. Product.call(this) is like super. With a helper and following conventions it helps to see this relation:
Function.prototype.inherits = function(parent) {
this.prototype = Object.create(parent.prototype); // inherit parent's prototype
this.prototype.constructor = this; // point to the right constructor
};
// A "class"
var Product = (function(){
// constructor
function Product(name, price) {
this.name = name;
this.price = price;
}
return Product;
}());
var Food = (function(_super){
Food.inherits(Product); // inherit Product's prototype methods
function Food(name, price) {
// call "super" to inherit instance properties
_super.call(this, name, price);
this.category = 'food';
}
}(Product)); // the parent class AKA "super"
It is not 100% equivalent, but this should give you a general idea of how inheritance works in JS compared to other languages. It can look pretty similar as you see.
In function Food(name, price) it inherits the constructor's Product's properties with Product.call(this).
Not really. It applies the Product's constructor to the new Food instance, executing its code with e.g. the negative price check.
A "byproduct" is that the constructor creates instance-specific properties on the object, yes.
What is Food.prototype = Object.create(Product.prototype); doing? Is it adding another prototype to Food(if that is even possible to have 2 prototypes)?
Exactly. It is chaining the prototypes. The instances of Food that are created by new Food will inherit properties (including methods) from Food.prototype, which will (by that statement) inherit properties from Product.prototype.
You can't see much of this behaviour currently as your prototype objects do not have any methods yet. Add some (maybe an "output" method?) and check the results.
Simple minimalistic inheritance library: (2kb minified) https://github.com/haroldiedema/joii
It basically allows you to do the following (and more):
// First (bottom level)
var Person = new Class(function() {
this.name = "Unknown Person";
});
// Employee, extend on Person & apply the Role property.
var Employee = new Class({ extends: Person }, function() {
this.name = 'Unknown Employee';
this.role = 'Employee';
this.getValue = function() {
return "Hello World";
}
});
// 3rd level, extend on Employee. Modify existing properties.
var Manager = new Class({ extends: Employee }, function() {
// Overwrite the value of 'role'.
this.role = this.role + ': Manager';
// Class constructor to apply the given 'name' value.
this.__construct = function(name) {
this.name = name;
}
// Parent inheritance & override
this.getValue = function() {
return this.parent.getValue().toUpperCase();
}
});
// And to use the final result:
var myManager = new Manager("John Smith");
console.log( myManager.name ); // John Smith
console.log( myManager.role ); // Manager
console.log( myManager.getValue() ); // HELLO WORLD

How to clone a constructor in JavaScript?

I have a constructor Monkey():
function Monkey(name, age) {
this.name = name;
this.age = age;
}
I want to make another constructor named Human() with an extra property cars which will store number of cars the person has along with all the property that Monkey has (like name and age)
I don't want to repeat all the Monkey stuff in the new Human stuff. Is is possible to clone the Monkey and extend a property with prototype?
I've tried this code, I guess it's what you want:
function Human(name,age,cars){
Monkey.call(this,name,age);
this.cars = cars;
}
This way, the Human constructor calls the Monkey constructor as a normal function, but setting its namespace as the new Human object. Thus, in this case, the this keyword inside Monkey constructor refers to a object of class Human, and not Monkey. Also, with this code, the condition new Human() instanceof Human; returns true, since I'm not returning a new instance of Monkey, just using its constructor.
Also, you can "clone" the prototype, as you said. Just do this:
Human.prototype = Monkey.prototype;
EDIT
As #Bergi amd suggested, the best way to clone a prototype is using the Object.create method, as follows:
Human.prototype = Object.create(Monkey.prototype, {constructor:{value:Human}});
I'm writing this answer simply to complement the others, it SHOULD NOT be used unless you fully know the impact of using the non-standard __proto__.
function Monkey(name, age) {
this.name = name;
this.age = age;
}
function Human(name, age, cars) {
this.__proto__ = new Monkey(name, age);
this.cars = cars;
}
console.log(new Human(1, 2, 3));
See also
__proto__, when will it be gone? Alternatives?
JavaScript and __proto__ - what browsers use it?
Simple start for functional style/parasitic'ish inheritance:
function Human(name, age, cars) {
var that = new Monkey(name, age);
that.cars = cars;
return that;
}
As outlined by Douglas Crockford
http://www.crockford.com/javascript/inheritance.html

Inheritance in JS: this.base = Class(); this.base() or ...?

I am trying to "get" inheritance in JS.
I just discovered a neat way to basically copy all properties from one object into another:
function Person(name){
this.name="Mr or Miss: "+name;
this.introduce = function(){
console.log("Hi, I am "+this.name);
}
}
function Employee(name,title){
this.title=title;
this.base=Person;
this.base(name);
}
e = new Employee('tony', 'manager')
e.introduce();
Note that I have a Person() class with a constructor, and its attribute "name" is generated by the constructor.
The great thing about this is also that then employee has ALSO the name in the constructor -- and voila', it creates the Person object using the same parameter.
If I had done this with the "Prototype" way:
function Person(name){
this.introduce = function(){
console.log("Hi, I am "+this.name);
}
}
function Employee(name, title){
this.name = name; /* ?!?!?!?!? I can't call the proper constructor here */
this.title = title;
}
Employee.prototype= new Person(); /* ?!?!? NO NAME HERE..>? */
Employee.prototype.constructor = Employee;
e = new Employee('tony', 'manager')
e.introduce();
Err.... now what? I can't even complete this: this.name in Employee cannot be set using the proper Person constructor; the creation of a Person object happens only once in the inheritance.
So... what am I missing? Is the first example I gave "the" way to go in my case? And is there a way to have the same result with the second example?
Help!
This kind of prototype inheritance is often done this way:
function Parent() {}
function Child() {
Parent.call(this); // call the constructor of the parent
}
var Constr = function() {};
Constr.prototype = Parent.prototype;
Child.prototype = new Constr();
Child.prototype.constructor = Child;
So the "trick" is to assign the Parent.prototype as prototype to an empty function and set a new instance of this function as prototype of Child.
This is done so that extending Child.prototype does not extend Parent.prototype.
You also have to call the parent's constructor in the child's constructor. I guess this is the part you struggled with. Every function has a call [docs] and apply [docs] method which let's you explicitly set the element this should refer to inside the function.
In your example, it would look like:
function Employee(name,title){
this.title=title;
Person.call(this, name);
}
without assigning the constructor to a property of the instance.
In your example, this.base(name) works, because through assigning the constructor to a property of the instance (and calling it this way), this inside the function refers to that instance.
There are several libraries implementing this pattern, e.g. Google Closure library:
goog.inherits = function(childCtor, parentCtor) {
/** #constructor */
function tempCtor() {};
tempCtor.prototype = parentCtor.prototype;
childCtor.superClass_ = parentCtor.prototype;
childCtor.prototype = new tempCtor();
childCtor.prototype.constructor = childCtor;
};

Categories