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.
Related
I come from a conservative OOP language (JAVA) and dont really understand Javascript inheritance. I am also shaky with the whole Prototype concept but I have seen an example here that answers my need but I dont understand the details and why things are not done differently.
Taking their example, the correct implementation is as follows
function Animal(name) {
this.name = name;
}
// Example method on the Animal object
Animal.prototype.getName = function() {
return this.name;
}
function Mammal(name, hasHair) {
// Use the parent constructor and set the correct `this`
Animal.call(this, name);
this.hasHair = hasHair;
}
// Inherit the Animal prototype
Mammal.prototype = Object.create(Animal.prototype);
// Set the Mammal constructor to 'Mammal'
Mammal.prototype.constructor = Mammal;
I do not understand the purpose of the Object.call() function nor do i understand why Object.create() was used and not simply just Animal.prototype. Also why is the constructor being added in the last line? Is it because it is erased in the step before? And what should I do if I wanted to share code in among all Mammal instances?
Thanks in advance
If you did not call the Mammal.prototype.constructor = Mammal; then the constructor would be Animal() (which is the constructor of Animal.prototype by default)
Using Object.create() means Mammal.prototype is not a reference to Animal.prototype but instead a new object inheriting that prototype.
And using Object.call() ensures the scope is not that of the function calling the method and instead is the scope of the Mammal constructor.
Javascript can not extend classes like Java does. You can only simulate something like that.
Animal.call make sure the animal.this does not point to animal but rather point to Mammal. In short the call() function overwrites #this.
object.create simply creates an instance of an empty function with given object as prototype:
Object.create = function (o) {
function F() {};
F.prototype = o;
return new F();
}
Its only needed when using a child constuctor. If not a simple object will do it as well.
Here is a good advice:
http://javascriptissexy.com/oop-in-javascript-what-you-need-to-know/
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'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/
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.