Can you please explain the difference between two codes mentioned below ?
function Person(){}
Person.prototype.dance = function(){};
function Ninja(){}
Ninja.prototype = Person.prototype;
and
function Person(){}
Person.prototype.dance = function(){};
function Ninja(){}
Ninja.prototype = new Person();
I am little confused at these lines:
Ninja.prototype = Person.prototype;
and
Ninja.prototype = new Person();
I came to know the second one supports Inheritance and the first one not, Can you explain me what is the magic in the second one?
Setting Ninja.prototype = Person.prototype; is saying that all Ninjas are Persons, and all Persons are Ninjas, since it simply makes the two prototypes point to the same thing. So changing Ninja.prototype will change Person.prototype and vice versa.
Setting Ninja.prototype = new Person(); is saying that all Ninjas start off being a regular person, but Ninja.prototype can be modified without changing the definition of Person. The key here is the new keyword, which creates a unique instance of Person, and is therefore free to be modified without affecting anything else.
Example of Ninja.prototype = Person.prototype
Define Ninja's prototype to be the same as Person's:
function Person() {}
Person.prototype.dance = function () {}; // A Person can dance
function Ninja()
Ninja.prototype = Person.prototype; // Now a Ninja can dance too!
An instance of Ninja has the abilities of Person:
var ninja = new Ninja();
ninja.dance();
But, modifications to the definition of Ninja also affect instances of Person:
Ninja.prototype.kill = function () {}; // Oh no! Now a Person can kill too!
var bob = new Person();
bob.kill(); // Not what we wanted...
Example of Ninja.prototype = new Person()
Define Person in the same way as before:
function Person(){};
Person.prototype.dance = function () {}; // A Person can dance
Now I'll break Ninja.prototype = new Person() into two steps. First, create a new Person, called defaultNinja:
var defaultNinja = new Person(); // Despite the name, it's just a regular Person
Then define all Ninjas to be like the default:
function Ninja(){};
Ninja.prototype = defaultNinja; // Really the same as Ninja.prototype = new Person();
This time if we change what Ninjas can do:
Ninja.prototype.kill = function () {};
// OR,
defaultNinja.kill = function () {};
Instances of Person aren't affected:
ninja.kill(); // Now the ninja can kill
var bob = new Person();
bob.kill(); // ERROR, because Person.prototype doesn't have kill(),
// only defaultNinja does
Related
The book "JavaScript for Ninja" suggested the following fix for constructor property while establishing prototypical chain between objects:
If I create a Person object as follow:
var person = new Person();
alert(person.constructor == Ninja); // Display true
Even though its fix the problem that ninja.constructor will refer to the Ninja function, But it creates the another problem that now person.constructor will also refer to the Ninja function instead of Person.
Reproducible Example:
function Person() {
}
var person = new Person();
Person.prototype.dance = function() {};
function Ninja() {
}
Ninja.prototype = person;
Object.defineProperty(Ninja.prototype, "constructor", {
enumerable: false,
value: Ninja,
writable: true
})
var ninja = new Ninja();
alert(person.constructor == Ninja); // Display true
I am unable to understand why this fix was suggested by the author.
You're only modifying the constructor property of that one person instance, not the whole Person class. If you do
person2 = new Person();
console.log(person2.constructor == Ninja);
it will print false.
Notice that in the book you quoted, it didn't even assign the new Person() object to a variable, it just created an anonymous object for use in creating the prototype chain.
In general, the object used in the prototype chain will not usually be used as an actual object in the application, it just serves the purpose of linking the related classes.
function Person() {
}
var person = new Person();
Person.prototype.dance = function() {};
function Ninja() {
}
Ninja.prototype = person;
Object.defineProperty(Ninja.prototype, "constructor", {
enumerable: false,
value: Ninja,
writable: true
})
var ninja = new Ninja();
var person2 = new Person();
console.log(person.constructor == Ninja);
console.log(person2.constructor == Ninja);
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).
I'm trying to use the revealing prototype patter to extend a "class". As an example I have an Animal and a Fish.
Here's what I'd like to be able to to:
Fish to Inherit the prototype from Animal
Override members of Animal if needed
Add new members to the Fish prototype
Do all this while still using the revealing prototype pattern for both "classes"
I can create the Animal "class":
var Animal = function(data) {
this.name = ""
this.color = "";
this.weight = 0;
};
Animal.prototype = function() {
var eat = function() {
document.write(this.name + " is eating.<br>");
}
return {
constructor: Animal,
eat: eat
};
}();
And I can create a Fish "class" that inherits from Animal:
var Fish = function(data) {
this.isSwimming = false;
};
Fish.prototype = new Animal();
The prototype for the Fish is where I'm running into trouble. Is it possible to use the revealing prototype pattern for Fish and still inherit the prototype from Animal and override Animal if needed? (I'm not completely opposed to using a third party library to do this, but I'd prefer not to.) For example, how could I override eat() and add a new function to Fish called swim?
Edit:
Here's what I've come up with. This seems to do what I need. Am I missing anything?
Fish.prototype = new function(proto) {
var base = proto.constructor;
var eat = function(data) {
new base().eat (data);//This is just to show you can call the base. If needed.
document.write("fish eating.<br>");
};
var swim = function(){
document.write("fish is swimming.<br>");
};
var thisProto = {
constructor: Fish,
eat: eat,
swim: swim
};
for (var propt in thisProto) {
proto[propt] = thisProto[propt];
}
return proto;
}(new Animal());
Edit:
In the answer I accepted, one of the main points was to not use the new keyword. So I researched the difference between the new keyword and Object.create(). If I understand things correctly, they both do basically the same thing, but Object.create() will not call the objects constructor while the new keyword will. If you need to inherit something that is defined in the constructor, you'll need to use the new keyword or move that member to the prototype.
Here's a plunk that I used to experiment with this some more: http://plnkr.co/edit/322WB4jyCJberABbb0P0
Am I missing anything?
Yes.
new function(proto) {
Do not use new.
new base().eat (data);//This is just to show you can call the base. If needed.
Do not use new. You'd create a new instance here, however what you want is get the eat method from the base.prototype and call that on your Fish instance.
proto = new Animal()
Do not use new!
Fish.prototype = (function(super) {
var proto = Object.create(super);
function eat(data) {
super.eat.call(this, data);
document.write("fish eating.<br>");
}
function swim(){
document.write("fish is swimming.<br>");
}
proto.constructor = Fish;
proto.eat = eat;
proto.swim = swim;
return proto;
})(Animal.prototype);
var Person = function(name){
this.name = name;
};
console.log("1 " + typeof(Person.prototype)) //"object" - prototype is a property of a first class functional object
Person.prototype.sayhi = function(){console.log("hi")};
var john = new Person();
console.log("2 "+typeof(Person.sayhi)) // "undefined"
console.log("3 "+typeof(john.sayhi))// "function"
I am trying to get a better understanding of javascript prototype.
I wonder why case 2 returns undefined, while case 3 returns "object" as it should.
I read up on other posts but can't seem to find the answer. Thanks.
Functions attached to the prototype (Person.prototype) are not accessible from a constructor (Person), that is Person.sayhi is not trying to access the prototype at all.
When you call a constructor (say var p = new Person()), Person.prototype is attached to the prototype chain of the created object (p), that's why you can call p.sayhi(). However, sayhi is never attached to the constructor
Because your "2" console.log isn't looking at the prototype:
Person.sayHi = function() { console.log('I am not in an instance'); }
console.log(typeof(Person.sayHi)); //"function"
var john = new Person();
console.log(typeof(john.sayHi)); //"undefined"
is different than:
Person.prototype.sayHi = function() { console.log('Hi'); }
console.log(typeof(Person.sayHi)); //"undefined"
console.log(typeof(Person.prototype.sayHi)); //"function"
var john = new Person();
console.log(typeof(john.sayHi)); //"function"
sort of the difference between static and instance methods in c#/java
I'm quite new to Prototypal inheritance in JavaScript and I'm trying to understand what's the issue here.
Simple code, we have two objects pet and pet2, pet2 inherits from pet.
var Pet = function() {
this.type="Dog";
this.age = 4;
};
var Pet2 = function() {
this.breed = "Kashon";
};
pet = new Pet();
pet2 = new Pet2();
if (Object.create !== 'function') {
Object.create = function(oldObject) {
function F() {}
F.prototype = oldObject;
return new F();
};
}
pet2 = Object.create(pet);
The issue is that when I try to access pet2.breed, it's undefined for some reason, why is this?
alert(pet2.type); //ok
alert(pet2.age); //ok
alert(pet2.breed); //comes out undefined?
Any help would be nice :D
When you use use Object.create you are assigning old object as prototype (eg, Pet). Of course, no properties of Pet2 would be there. You should "inherit" objects using prototype like: Pet2.prototype = new Pet;
var Pet = function() {
this.type="Dog";
this.age = 4;
};
var Pet2 = function() {
this.breed = "Kashon";
};
Pet2.prototype = new Pet; // Pet2 inherits Pet
pet = new Pet();
pet2 = new Pet2();
alert(pet2.type); //ok
alert(pet2.age); //ok
alert(pet2.breed); // ok?
http://jsfiddle.net/U66aX/
A number of problems here.
You are mixing pseudo-classical with prototypal inheritance. Not that it can't be done, but I would stick with one of them only. Since you're asking about prototypal, you should stay away from new (except inside your Object.create function)
You are setting pet2 twice, therefore overriding your initial assignment that made it an instance of Pet2.
You're never saying that Pet2 inherits from Pet1
Here's what the prototypal example would look like: http://jsfiddle.net/NsRMA/
var Pet1 = {
type: "Dog",
age: 4
};
// Make Pet2 inherit from Pet1
var Pet2 = Object.create(Pet1);
// Add new properties to Pet2, this can and should be done
// by passing another argument to Object.create , but any
// hacked version can't support it
Pet2.breed = "Kashon";
// Now create an object that inherits from Pet2 (and consequently, Pet1)
var pet = Object.create(Pet2);
alert(pet.type); //ok
alert(pet.age); //ok
alert(pet.breed); //ok