I've been learning prototypical inheritance in JavaScript from John Resig's Secrets of the JavaScript Ninja, and I was wondering what happens in the following code example (that I just made up).
function Person() {}
Person.prototype.sayHello = function() {
alert("Hello World");
}
function Ninja() {}
Ninja.prototype.swingSword = function() {
alert("I can swing my sword.");
}
Ninja.prototype = new Person();
var ninja1 = new Ninja();
As far as I know, the result of all of these lines of code is that the variable ninja1 references a Ninja object, that through its prototype, has the swingSword method, and through prototypical inheritance of Person's prototype, has the sayHello method.
Where I am confused is in the following: since the property swingSword (which happens to be a method) was attached to Ninja's prototype before a person instance was assigned to Ninja's prototype, wouldn't the swingSword property/method be overwritten by the later assignment of the Person instance? If not, how can Ninja's prototype property, which references the prototype object, reference both the Person instance, and have a swingSword property?
[...] that through its prototype, has the swingSword method, [...]
While the rest of that statement is correct -- that ninja1 references Ninja (well, technically, Ninja.prototype) and will have a sayHello through inheritance -- your later thoughts are correct regarding swingSword.
wouldn't the swingSword property/method be overwritten by the later assignment of the Person instance?
At the end of your snippet, ninja1.swingSword should be undefined.
console.log(typeof ninja1.swingSword); // 'undefined'
// as is:
console.log(typeof Ninja.prototype.swingSword); // 'undefined'
After Ninja.prototype = ..., the original prototype object that swingSword was attached to is no longer being referenced. So, it won't be used when creating new instances.
If you intend to set a new prototype object, you'll want make sure that's done before modifying it.
Ninja.prototype = new Person();
Ninja.prototype.swingSword = function() {
alert("I can swing my sword.");
}
var ninja1 = new Ninja();
console.log(typeof ninja1.swingSword); // 'function'
And, if ninja1 actually does have a swingSword, it probably means that it was created before the prototype was changed.
Objects retain their own [[Prototype]] reference from when they were created regardless of what changes may be made to their constructor's prototype property.
Ninja.prototype.swingSword = function() {
alert("I can swing my sword.");
}
var ninja1 = new Ninja();
Ninja.prototype = new Person(); // won't affect existing instances
var ninja2 = new Ninja();
console.log(typeof ninja1.swingSword); // function
console.log(typeof ninja2.swingSword); // undefined
Example of each: http://jsfiddle.net/G8uTk/
Related
Initially I assigned function object to variable Person. At this moment, Person's proto is pointing to Function.prototype. Then I added some functions to Person.prototype. When I call Person constructor with new keyword below and assign it to var test, as far as I know, it sets test proto to Person.prototype. This Person.prototype is an object, with getName mapped to a function. So when I call test.getName(), it searches for the function in test.prototype and if it doesn't find it there, then it will search for the function in its proto i.e. Person.prototype.
Now suppose I create another function object and assign it to variable Customer. It's proto would be pointing to Function.prototype. Then for inheritance we should do Customer.prototype = new Person(). I am confused about why I should do this? Does it sets Customer's proto to Person.prototype. If it does , then shouldn't I just write Customer = new Person(). If it doesn't than, do Customer proto still points to Function.prototype or is there something else that I am missing ?
var Person = function(name) {
this.name = name;
console.log("Running the constructor of Person " + name)
}
Person.prototype.getName = function() {
return this.name;
}
var test = new Person("Yolo");
console.log(Person.prototype.getName.call(test))
console.log(test.getName());
var Customer = function(name) {
this.name = name;
console.log("Running the constructor of Customer " + name)
};
Customer.prototype = new Person();
Thanks in advance !
There are two different concepts here:
__proto__ is the object's parent in the inheritance tree.
prototype is a function's property which defines what the __proto__ will be of any objects it creates when used as a constructor.
Since constructors are objects themselves (function objects), they also are in an inheritance tree, but that tree has nothing to do with the inheritance tree of the objects created by these constructors. They are two separate worlds.
Look at this code, which illustrates the inheritance chain for a customer object:
var cust = new Customer('Jack');
console.log(cust.__proto__ === Customer.prototype); // true
console.log(cust.__proto__.__proto__ === Person.prototype); // true
console.log(cust.__proto__.__proto__.__proto__ === Object.prototype); // true
So here we followed the prototype chain of the cust object. This is an entirely different chain from the chains for the constructors (functions):
console.log(Customer.__proto__ === Function.prototype); // true
console.log(Person.__proto__ === Function.prototype); // true
console.log(Object.__proto__ === Function.prototype); // true
Nothing unusual here: they are functions. Also, it is not necessary to change anything to that. As said, it does not relate to the inheritance for the objects these constructors create.
Note that you should never need to access the __proto__ property. The above is only provided for illustrating the inheritance chain.
Customer.___proto____ = Function.prototype
It will always be pointing to the Function prototype
Customer.prototype = new Person();
This statement will make Customer.prototype._____proto_____ point towards Person.Prototype
Customer._____proto_____ will never change only its prototype 's ____proto___ changes by inheritance
I found this image useful. It shows all the links clearly.
I'm reading through Crockford's "Javascript: The Good Parts". Early on he introduces the Object.create() function, and it seems to be redundant. Why is Object.create() preferred to assigning an object to the prototype of a new object the good ol' fashioned way? What's the difference between these two statements? I certainly prefer the Object.create() syntax, but I'd like to understand the fundamentals here:
var bar = Object.create(foo);
and
var bar = {};
bar.prototype = foo;
How it works is ,
function createObject(proto) {
function ctor() { }
// assigns prototype of Person to ctor's prototype
ctor.prototype = proto;
// return new instance of ctor
return new ctor();
}
// Usage:
Student.prototype = createObject(Person.prototype);
So, it creates new object constructor with prototype assigned as prototype of Person.
When you try to add a new function in Student's prototype object, it is not available in Person's prototype
ex -
Student.prototype = createObject(Person.prototype);
Student.prototype.newFunc1 = function() { console.log('hello from new world');}
//Person.prototype will not have newFunc1.
In case of where you directs assigns prototype of Person to prototype of Student like
And when you add a new function into prototype of Student like
Student.prototype = Person.prototype;
Student.prototype.newFunc1 = function() { console.log('hello from new world');}
//When you check Person.prototype, it will have newFunc1 function.
prototype object is not assigned, only the reference is assigned.
In object oriented programming, the child class has properties of parent as well as its own.
If we don't do Object.create() and directly assign prototype of parent to the prototype of child , whatever new property we add to the child, will get reflected in parent too.
To avoid that, Object.create() is preferred.
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?
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.
At the moment, I try to understand the Javascript prototype object.
Following situation:
// new Person object
function Person () {
this.greeth = function() {
console.log("Good morning, " + this.name);
};
};
// add new function to Person.prototype for inheritance
Person.prototype.sayWeight = function() {
console.log(this.weight);
};
// create new friend object
var friend = {
forename: "Bill",
lastname: "Gates",
weight: 78,
sayhello: function() {
console.dir("Hello " + this.forename + ' ' + this.lastname);
}
};
// assign Person.prototype to friend.prototye (inheritance)
friend.prototype = Person;
console.dir(friend);
Now my question:
I assign the Person Object to my friend.prototype .
For my understanding, "friend" should have all the functions of Person.prototype (i.e. sayWeight() cause of friend.prototype = Person; ).
But the only function I can call is friend.sayhello.
In my output (console.dir(friend);), I can see the sayWeight() function, but when I call it, I get an error (TypeError: Object #<Object> has no method 'sayWeight')
Can you explain this behavior? Why can't I access the sayWeight() function?
=========================================================
Another question:
function Person() {
this.name = "Bill Gates";
this.weight = 78;
this.sayHello = function() {
console.log("Hello " + this.name);
}
}
Person.prototype.sayWeight = function() {
console.log(this.weight);
}
var friend = new Person();
What is the difference between the sayWeight and the sayHello function? The sayWeight function is in the prototype-object of Person - okay, but what advantages do I have from prototype in this case?
Can you explain this behavior? Why can't I access the sayWeight() function?
Because you can't change the prototype of an object after you create it. You are setting the prototype property, but the internal prototype reference that is used by the javascript interpreter, namely __proto__ is still the one used in effect, and currently __proto__ is referring to Object.prototype.
If you changed this line friend.prototype = Person; to this one friend.__proto__ = Person.prototype; then everything will work.
If your browser supports ES5 then you can use Object.create() to create objects that inherit from a given prototype, or you can use a workaround adopted from the book Javascript: The Good Parts, and twisted a little by David Flanagan in his book: Javascript The Definitive Guide:
// inherit() returns a newly created object that inherits properties from the
// prototype object p. It uses the ECMAScript 5 function Object.create() if
// it is defined, and otherwise falls back to an older technique.
function inherit(p) {
if (p == null) throw TypeError(); // p must be a non-null object
if (Object.create) // If Object.create() is defined...
return Object.create(p); // then just use it.
var t = typeof p; // Otherwise do some more type checking
if (t !== "object" && t !== "function") throw TypeError();
function f() {}; // Define a dummy constructor function.
f.prototype = p; // Set its prototype property to p.
return new f(); // Use f() to create an "heir" of p.
}
NOTE __proto__ isn't a standardized property and shouldn't be used in production code, or as #alex noted in his comment it is on the way of standardization.
NOTE 2: As #thg435 mentioned in his comment, an alternative to using the __proto__ property is using Object.setPrototypeOf() which is standardized in ES6.
EDIT TO COVER LAST QUESTION
What is the difference between the sayWeight and the sayHello function ?
The difference is that now each new instance of Person (for example new Person()) will have a distinct sayHello() function, but a shared sayWeight() function.
var friend = new Person();
var anotherFriend = new Person();
console.log(friend.sayHello === anotherFriend.sayHello); // OUTPUTS FALSE
console.log(friend.sayWeight === anotherFriend.sayWeight); // OUTPUTS TRUE
what advantages do I have from prototype in this case?
Well less memory, code reuse across all instances of person, and if you already have one or more person objects and you want to add a new method to all of them without modifying each one in turn then you can add that method to the prototype and they will all inherit from it.
Person doesn't inherit Person.prototype, only instances of Person do. Further, with a normal Object say foo = {}, foo.prototype is just a normal property. You'd either need a constructor or to create the initial object defining it as having a specific prototype.
What you actually want is
friend = Object.create(Person.prototype);
// or, for older browsers
friend = new Person();
// or some Object.create shim
/* which gives you
friend inherits Person.prototype
inherits Object.prototype */
This sets up the prototype chain. If you want to create many friends, it may be better to set up a new constructor Friend, which has Friend.prototype = Object.create(Person.prototype);. This also protects Person.prototype from if you want to add properties to Friend.prototype. Then you would have
(instanceof) Friend inherits Friend.prototype
inherits Person.prototype
inherits Object.prototype
I asked the question:
Why cant I declare a constructor instantiate an object and then access the prototype?
And you can see that I have marked the answer. I understand the response but Im a bit confused as to what he means by:
The prototype belongs to the class, not the instance:
Does this mean that javascript has a class in this example? I thought javascript was classless? It only has function constructors... At what point does a function constructor become a class? Is it when you add other members to it using the .prototype accessor?
Actually class is an OOP term, not really javascript. What is meant is that the prototype belongs to the constructor. So in
function MyConstructor(prop){
this.foo = prop || 'foo';
}
MyConstructor.prototype.bar = 'allways bar';
var mc1 = new MyConstructor('I am mc1'),
mc2 = new MyConstructor('I am mc2');
alert(mc1.bar) ; //=> allways bar
alert(mc2.bar) ; //=> allways bar
alert(mc1.foo) ; //=> I am mc1
alert(mc2.foo) ; //=> I am mc2
bar belongs to the constructors (MyConstructor) prototype. It will always be 'allways bar', for every instance. foo is an instance property (with a default value 'foo') and can be assigned with a different value for every instance.
Ya prototype of JavaScript is a concept quite similar to class but not exactly the same. Read the article below, it offers one of the best explanations available on internet on this issue.
http://www.crockford.com/javascript/inheritance.html
There are no classes in javascript.
Constructors are functions and have a prototype property that references an object. You can add functions to that object, or assign a new object to the prototype property to create an inheritance chain:
function MyConstructor () {
// initialise instance
}
MyConstructor.prototype.someMethod = function() {
// ...
};
MyConstructor.prototype.anotherMethod = function() {
// ...
};
or replace it with an instance of another constructor:
MyConstructor.prototype = new SomeOtherConstructor();
MyConstructor.prototype.constructor = MyConstructor;
and so on. Now when an instance of MyConstructor is created:
var anInstance = new MyConstructor();
The object returned by the constructor has MyConstructor.prototype as its internal [[prototype]] property and "inherits" its methods and properties (and those on its entire [[prototype]] chain).
So each instance of MyConstructor has its MyConstructor.prototype on its prototype chain. Note however that MyConstructor doesn't inherit from it's own prototype, it is only used by instances created by new MyConstructor.