I am learning javascript and got puzzled. An example over here which has example as below:-
// define the Person Class
function Person() {}
Person.prototype.walk = function(){
alert ('I am walking!');
};
Person.prototype.sayHello = function(){
alert ('hello');
};
// define the Student class
function Student() {
// Call the parent constructor
Person.call(this);// <---- Confusion
}
// inherit Person
Student.prototype = new Person(); //<---- Confusion
// correct the constructor pointer because it points to Person
Student.prototype.constructor = Student;
// replace the sayHello method
Student.prototype.sayHello = function(){
alert('hi, I am a student');
}
// add sayGoodBye method
Student.prototype.sayGoodBye = function(){
alert('goodBye');
}
var student1 = new Student();
student1.sayHello();
student1.walk();
student1.sayGoodBye();
// check inheritance
alert(student1 instanceof Person); // true
alert(student1 instanceof Student); // true
Now, I am confused (<----) in these two lines. When I say Person.call(this);, this is simply stating to Inherit properties of Person class... Right?
Then what is this doing?
// inherit Person
Student.prototype = new Person(); //<---- Confusion
As per my knowledge, .prototype also inherits all properties?
-
I may sound very silly to people who are expert in javascript. But will feel much happy if you please comment and down vote.user2511749– user25117492013年10月28日 09:35:15 +00:00Commented Oct 28, 2013 at 9:35
-
this is different things you should learn more about call and apply methods of javascript this is will be very useful if you want learn this programing languageMax– Max2013年10月28日 09:37:22 +00:00Commented Oct 28, 2013 at 9:37
-
3I don't see any reason for downvoting this question either. Prototypical inheritance is tricky to understand, and there's a lot of unclear and outright incorrect information out there.T.J. Crowder– T.J. Crowder2013年10月28日 09:48:33 +00:00Commented Oct 28, 2013 at 9:48
1 Answer 1
To explain it, first let's remember how constructor functions work in JavaScript:
function Guide(a) {
this.a = a;
}
Guide.prototype.q = "Life, the Universe, and Everything";
var g = new Guide(42);
console.log(g.q); // "Life, the Universe, and Everything"
console.log(g.a); // 42
When we do new Guide(42), the new operator creates a new object and assigns it a prototype using the Guide.prototype property. Then new calls Guide, passing in that new object as this. Guide uses this to add properties to the new object that aren't on its prototype. Then the new expression completes and its result is the new object that it created.
When we look at g.q, since the g object doesn't have its own property called q, the JavaScript engine looks at g's prototype, which (again) it got assigned when it was created. That prototype has a q property, and so the engine uses its value.
In contrast, when we look at g.a, the g object has its own property called a, and so the value is used directly.
With that foundation in place, let's look at Student and Parent:
function Student() {
// Call the parent constructor
Person.call(this);// <---- Confusion
}
When we call new Student(), within the call to Student, this is (again) the new object created by the new operator, which has Student.prototype as its underlying prototype. But the Parent function hasn't had a chance to do anything with this new object. So what that line does is give Parent a chance to do whatever it needs to do to new objects that it can't do via the prototype, like our Guide function earlier assigning to this.a. In technical terms, Parent.call(this); calls the Parent function, ensuring that this within the call to Parent is the value passed into call (which is, in this case, the this of the call to Student — e.g., the new object). If you're familiar with class-based languages, this is like doing super(); (that's Java, but you get the idea) in a derived constructor: It gives the base constructor a chance to initialize the object.
// inherit Person
Student.prototype = new Person(); //<---- Confusion
Since Student is supposed to inherit from Person, what that code is doing is creating the prototype that will be assigned to objects created via new Student. The object it's creating is a Person object.
FWIW, that code isn't quite implementing the construction chain correctly (it's calling Person more often than it should [both when creating Student.prototype and when Student is called], and failing to set constructor).
The more correct way to create Student's prototype property, if we're going to call Parent from within Student, looks like this:
function derive(child, parent) {
function ctor() { this.constructor = child; }
ctor.prototype = parent.prototype;
child.prototype = new ctor();
}
derive(Student, Parent);
That way, we get a prototype based on Parent.prototype but without calling Parent. It's an either-or: Either call Parent to create Student.prototype, or call Parent within Student, but don't do both. When building hierarchies with constructor functions, typically you want to call the parent from the child constructor, rather than when creating the child prototype. When using direct object inheritance (without constructor functions), of course you do it the other way.
If you're interested in inheritance in JavaScript, I've written a helper script called Lineage you might want to look at, and in particular even if you don't use Lineage, this discussion on its wiki page may be useful for understanding inheritance hierarchies.