Confusion over Classical and Prototypal Inheritance Javascript - javascript

// Prototye Inheritance
var AnswerPrototype = {
constructor: function(value){
this._val = value;
},
get: function(){
return this._val;
}
}
var lifeAnswer = Object.create(AnswerPrototype);
lifeAnswer.constructor(100);
alert(lifeAnswer.get());
var desertAnswer = Object.create(AnswerPrototype);
desertAnswer.constructor(200);
alert(desertAnswer.get());
var firmAnswerProtoype = Object.create(AnswerPrototype);
firmAnswerProtoype.get = function(){
return AnswerPrototype.get.call(this);
}
var luckyAnswer = Object.create(firmAnswerProtoype);
luckyAnswer.constructor(1);
alert(luckyAnswer.get());
var magicAnswer = Object.create(firmAnswerProtoype);
magicAnswer.constructor(2);
alert(magicAnswer.get());
// Classical Inheritance
function Answer(value){
this._val = value;
}
Answer.prototype.get = function(){
return this._val;
}
var lifeAnswer = new Answer(100);
alert(lifeAnswer.get());
var desertAnswer = new Answer(200);
alert(desertAnswer.get());
function firmAnswer(value){
return Answer.call(this,value);
}
firmAnswer.prototype = Object.create(Answer);
firmAnswer.prototype.constructor = firmAnswer;
firmAnswer.prototype.get = function(){
return Answer.prototype.get.call(this);
}
var luckyAnswer = new firmAnswer(20);
alert(luckyAnswer.get())
Can anyone tell me on how the second one is classical and the first one is prototypal. I was watching the http://www.objectplayground.com/ and i am totally confused as in both the cases we use Object.create() and as well as prototype object.

First, to get it straight, Javascript only has prototypal inheritance. What you can do is simulate "classical" inheritance. The difference between the two boils down to the syntax with which objects are instantiated - "classical" inheritance uses the more familiar constructor functions and "new" operator, which hide the inherent prototypal nature of Javascript's object creation and inheritance properties.
Let's break down both cases a bit.
var AnswerPrototype = {
constructor: function(value){
this._val = value;
},
get: function(){
return this._val;
}
}
The prototype here is explicitly created, along with a "constructor" (or more properly named, initializing function).
var lifeAnswer = Object.create(AnswerPrototype);
lifeAnswer.constructor(100);
alert(lifeAnswer.get());
Now, creating objects is slightly clunky here. First you need to call Object.create(), and then you need to call the initializer function. This doesn't have to be the case though - here's a different sample prototype which does both in one swoop:
var AnswerPrototype = {
create: function(value){
var obj = Object.create(AnswerPrototype);
obj._val = value;
return obj;
},
get: function(){
return this._val;
}
}
var lifeAnswer = AnswerPrototype.create(100);
Simulating "classical" inheritance relies on letting developers use the more familiar constructor functions and "new" operator to create their objects, but since it it just masking the prototypal inheritance of Javascript, it remains essentially the same thing.
function Answer(value){
this._val = value;
}
Answer.prototype.get = function(){
return this._val;
}
This isn't much different from the prototypal inheritance one, except the Answer is decoupled from the now implicitly created prototype object(Which can be accessed via the Answer.prototype property)
var lifeAnswer = new Answer(100);
Practically, sugar for var lifeAnswer = Object.create(Answer.prototype); // Call Answer on the newly created object to initialize some values, e.g. with Answer.call(lifeAnswer, 100);
firmAnswer.prototype = Object.create(Answer);
firmAnswer.prototype.constructor = firmAnswer;
firmAnswer.prototype is just the implicitly created prototype, very similar to firmAnswerPrototype in the first case.
To answer your specific question, the reason why they use Object.create() here is because inheritance via new quickly becomes very clunky. You would need to do something like:
firmAnswer.prototype = new Answer();
But now you either need Answer to be an empty constructor(function Answer() {}), or explicitly differentiate between calling it with no arguments(to use for inheritance), and calling it with arguments(to use for instantiating "Answer" objects).

You have those backwards. The second one is prototypal because it uses the object's prototype property to inherit. This block
firmAnswer.prototype = Object.create(Answer);
firmAnswer.prototype.constructor = firmAnswer;
firmAnswer.prototype.get = function(){
return Answer.prototype.get.call(this);
}
is assigning an instance of Answer to firmAnswer's prototype. However, it's piss poor code, as it's not actually taking advantage of the inheritance, it's redeclaring the get function.
I would avoid this code altogether. Read Crockford's The Good Parts for a good distinction between the two types.
EDIT: To give a bit of an explanation (without referencing that code), here's the basic difference.
'Classical' inheritance in Javascript (the way I see it used) is when you override objects properties. You have an object with a foo and a bar method. You then use a library (like jQuery or Prototype) to call an extend method. The method takes two arguments, a base object and a child object. It takes all of the properties of the base object, inserts the properties of the child object (possibly overwriting) and then returns a new object that has a mix of both properties. There's a bit more to it, but that's the gist. It's just manipulating object properties without the prototype.
Prototypal inheritance uses Javascript's built in prototype. A prototype is a chain of objects (essentially). Let's say you have an object B that inherits from A. To create a C class that inherits from B, we create a function named C and then assign B to the prototype. Then, when a property is requested from C, Javascript will do the following:
Check if the property exists on the instance of C. If not:
Check if the property is on the prototype of B. If not:
Check if the property is on the prototype of A. If not:
Throw error.
Sorry if it's a little vague. I'm trying to simplify it a bit. There's a lot to the prototype in Javascript. I would suggest reading some of Crockford's materials.

How is the second one is classical and the first one is prototypal
Both are using prototypical inheritance, there are no classes in JavaScript.
The second one is called "classical" (sometimes "pseudoclassical") because it uses the class pattern and mimics the conventional class syntax (as known from Java) when objects are created with the new operator.
The only difference is the .prototype link from the constructor function to the prototype object and the shorter instantiation syntax with only one command instead of two, what happens behind is the same in both approaches.
As we can see in your example, also the inheritance between two "classes" is a bit different. In both approaches the child prototype object inherits from the parent prototype object, and in both approaches you can call parent ("super") methods by invoking the functions explicitly on the child instance. Yet, in the "classical" pattern you need to declare a new constructor function for the child (to reference it), while in your explicit prototypical approach the children are inheriting the parent's .constructor method.

Related

Whats the difference between JavaScript Inheritance using Prototype and method call? [duplicate]

What does the following code do:
WeatherWidget.prototype = new Widget;
where Widget is a constructor, and I want to extend the Widget 'class' with a new function WeatherWidget.
What is the new keyword doing there and what would happen if it is left out?
WeatherWidget.prototype = new Widget;
The new keyword calls Widget as a constructor and the return value is assigned to the prototype property. (If you would omit new, you would not call Widget unless you added an argument list, (). However, calling Widget that way might not be possible. It would certainly have the potential to spoil the global namespace if it is not strict mode code and the implementation is conforming to ECMAScript Ed. 5.x there, because then this in the constructor would refer to ECMAScript’s global object.)
But this approach actually comes from a really viral bad example in the old Netscape JavaScript 1.3 Guide (mirrored at Oracle, formerly Sun).
This way, your WeatherWidget instances will all inherit from the same Widget instance. The prototype chain will be:
[new WeatherWidget()] → [new Widget()] → [Widget.prototype] → …
This can be useful, but most of the time you would not want it to happen. You should not do that here unless you want all your WeatherWidget instances to share among them the property values they inherit from this Widget instance, and only through it, from Widget.prototype. Another problem is that you need to call the parent constructor this way, which may not allow to be called without arguments as you do, or would not initialize properly. It certainly has nothing to do with emulation of class-based inheritance as known, e.g., from Java.
The proper way to implement class-based inheritance in these prototype-based languages is (originally devised by Lasse Reichstein Nielsen in comp.lang.javascript in 2003, for cloning objects):
function Dummy () {}
Dummy.prototype = Widget.prototype;
WeatherWidget.prototype = new Dummy();
WeatherWidget.prototype.constructor = WeatherWidget;
The constructor prototype property should be fixed as well, so that your WeatherWidget instances w would have w.constructor === WeatherWidget as expected, and not w.constructor === Widget. However, be aware that it is enumerable afterwards.
This way, WeatherWidget instances will inherit properties through the prototype chain, but will not share property values among them, because they inherit from Widget.prototype through Dummy which has no own properties:
[new WeatherWidget()] → [new Dummy()] → [Widget.prototype] → …
In implementations of ECMAScript Ed. 5 and later, you can and should use
WeatherWidget.prototype = Object.create(Widget.prototype, {
constructor: {value: WeatherWidget}
});
instead. This has the additional advantage that the resulting constructor property is not writable, enumerable, or configurable.
The parent constructor will only be called if you call it explicitly, from WeatherWidget, for example with
function WeatherWidget (…)
{
Widget.apply(this, arguments);
}
See also Function.prototype.extend() in my JSX:object.js for how to generalize this. Using that code, it would become
WeatherWidget.extend(Widget);
My Function.prototype.extend() takes an optional second argument with which you can easily augment the prototype of WeatherWidget instances:
WeatherWidget.extend(Widget, {
foo: 42,
bar: "baz"
});
would be equivalent to
WeatherWidget.extend(Widget);
WeatherWidget.prototype.foo = 42;
WeatherWidget.prototype.bar = "baz";
You will still need to call the parent constructor explicitly in the child constructor, though; that part cannot reasonably be automated. But my Function.prototype.extend() adds a _super property to the Function instance which makes it easier:
function WeatherWidget (…)
{
WeatherWidget._super.apply(this, arguments);
}
Other people have implemented similar extensions.
According to some odd Javascript rules, new Widget actually invokes the constructor rather than returning a reference to the constructor. This question actually answers the question the difference between var a = new Widget() and var a = Widget().
In simple words, the new keyword tells Javascript to call the function Widget under a different set of rules than a regular function call. Going off the top of my head, the ones I remember are:
There is a brand new object created
Widget can use the this keyword to refer to that object.
If Widget does not return anything, this new object will be created.
This object will inherit a few additional properties that will indicate it was created by Widget that are used to track down property chains.
Without the new keyword, a call to widget would
If in strict mode, this will be set to undefined.
Otherwise, this will refer to the global object. (Called window by the browser.)
If the function does not return anything, then undefined will be returned.
Reference:
new keyword
WeatherWidget.prototype = new Widget;
does create a new instance of the Widget constructor and use it as WeatherWidget's prototype object. Using the new keyword creates the new object, sets up the inheritance chain of it to Widget.prototype, and applies the constructor function on it (where you can set up individual properties'n'methods, or create private-scoped variables).
Without the new keyword it would be an assignment of the Widget function to the prototype property - which does not make any sense. If you'd add the optional brackets (i.e. Widget()), it would invoke the function normally, but not as a constructor on a new instance, but with the global object as context. See also the reference for the this keyword.
Notice that you should not really use this code. As said, it creates a new instance by invoking the constructor function. But the purpose is only to create an empty object that inherits from the Widgets prototype object, not to instantiate something (which could do some harm, depending on the code). Instead, you should use Object.create (or its popular shim):
WeatherWidget.prototype = Object.create(Widget.prototype);
see also Javascript basic inheritance vs Crockford prototypical inheritance
In plain english you're extending one class with another. A prototype can only be an object so you set WeatherWidget's prototype to a new instance of Widget. If you removed the new keyword you would be setting the prototype to the literal constructor function which doesn't do anything.
var Appendages = function(){
this.legs = 2
};
var Features = function() {
this.ears = 4;
this.eyes = 1;
}
// Extend Features class with Appendages class.
Features.prototype = new Appendages;
var sara = new Features();
sara.legs;
// Returns 2.
Understanding that the prototype can be any object, something like this would also work:
var appendages = {
legs : 2
};
var Features = function() {
this.ears = 4;
this.eyes = 1;
}
// Extend Features class with Appendages class.
Features.prototype = appendages;
var sara = new Features();
sara.legs;
// Returns 2.
In JavaScript, if the key isn't found on the object, it checks the parents object you extended it from. Hence you can change items on the parent object on the fly like so:
var appendages = {
legs : 2
};
var Features = function() {
this.ears = 4;
this.eyes = 1;
}
// Extend Features class with Appendages class.
Features.prototype = appendages;
var sara = new Features();
sara.legs;
// Returns 2.
appendages.hair = true;
sara.hair;
// Returns true.
Note that this all happens during instantiation which means you can't just switch out the prototype after you've created the object:
var foo = {name : 'bob'};
var bar = {nachos : 'cheese'};
foo.prototype = bar;
foo.nachos;
// undefined
However, all modern browsers come with this newer __proto__ method, which allows you to do it:
var foo = {name : 'bob'};
var bar = {nachos : 'cheese'};
foo.__proto__ = bar;
foo.nachos
// "cheese"
Read up more on understanding JavaScript prototypes here.
This article from Pivotal Labs is also really good.
new is important for prototype inheritance; i.e.
Create a constructor with a method
var Obj = function(){};
Obj.prototype = {};
Obj.prototype.foo = function(){console.log('foo');};
Make a second constructor to extend the first with
var ExObj = function(){};
Now, if we prototype without new,
ExObj.prototype = Obj;
(new ExObj).foo(); // TypeError: Object #<Object> has no method 'foo'
Which means we haven't inherited from the prototype of Obj, however, if we prototype with new
ExObj.prototype = new Obj();
(new ExObj).foo(); // console logs 'foo'
Furthermore, adding new things to the prototype of ExObj doesn't make any changes to it's base, Obj.
JavaScript functions are "MULTIPLE(2) PERSONALITIES"!!!
They are regular-functions with input and output, which we call like function().
Also they are constructors of JS-objects, when we use the new keyword. >>>BUT<<< the new created objects are NOT INSTANCES of the constructors (like the objects of classes in class-based inheritance). The new objects are instances of the object of the prototype property of the constructor.
Then in WeatherWidget.prototype = you put the object you want to inherit its properties to the objects the constructor will create, which usually is new function() and not a function.
JavaScript created HUGE confusion in the programming community by naming the objects created by constructors, INSTANCES of them with the instanceof keyword.
> function f(){}
undefined
> new f() instanceof f
true

Javascript Inheritance and the funny behaviour of 'this' [duplicate]

What does the following code do:
WeatherWidget.prototype = new Widget;
where Widget is a constructor, and I want to extend the Widget 'class' with a new function WeatherWidget.
What is the new keyword doing there and what would happen if it is left out?
WeatherWidget.prototype = new Widget;
The new keyword calls Widget as a constructor and the return value is assigned to the prototype property. (If you would omit new, you would not call Widget unless you added an argument list, (). However, calling Widget that way might not be possible. It would certainly have the potential to spoil the global namespace if it is not strict mode code and the implementation is conforming to ECMAScript Ed. 5.x there, because then this in the constructor would refer to ECMAScript’s global object.)
But this approach actually comes from a really viral bad example in the old Netscape JavaScript 1.3 Guide (mirrored at Oracle, formerly Sun).
This way, your WeatherWidget instances will all inherit from the same Widget instance. The prototype chain will be:
[new WeatherWidget()] → [new Widget()] → [Widget.prototype] → …
This can be useful, but most of the time you would not want it to happen. You should not do that here unless you want all your WeatherWidget instances to share among them the property values they inherit from this Widget instance, and only through it, from Widget.prototype. Another problem is that you need to call the parent constructor this way, which may not allow to be called without arguments as you do, or would not initialize properly. It certainly has nothing to do with emulation of class-based inheritance as known, e.g., from Java.
The proper way to implement class-based inheritance in these prototype-based languages is (originally devised by Lasse Reichstein Nielsen in comp.lang.javascript in 2003, for cloning objects):
function Dummy () {}
Dummy.prototype = Widget.prototype;
WeatherWidget.prototype = new Dummy();
WeatherWidget.prototype.constructor = WeatherWidget;
The constructor prototype property should be fixed as well, so that your WeatherWidget instances w would have w.constructor === WeatherWidget as expected, and not w.constructor === Widget. However, be aware that it is enumerable afterwards.
This way, WeatherWidget instances will inherit properties through the prototype chain, but will not share property values among them, because they inherit from Widget.prototype through Dummy which has no own properties:
[new WeatherWidget()] → [new Dummy()] → [Widget.prototype] → …
In implementations of ECMAScript Ed. 5 and later, you can and should use
WeatherWidget.prototype = Object.create(Widget.prototype, {
constructor: {value: WeatherWidget}
});
instead. This has the additional advantage that the resulting constructor property is not writable, enumerable, or configurable.
The parent constructor will only be called if you call it explicitly, from WeatherWidget, for example with
function WeatherWidget (…)
{
Widget.apply(this, arguments);
}
See also Function.prototype.extend() in my JSX:object.js for how to generalize this. Using that code, it would become
WeatherWidget.extend(Widget);
My Function.prototype.extend() takes an optional second argument with which you can easily augment the prototype of WeatherWidget instances:
WeatherWidget.extend(Widget, {
foo: 42,
bar: "baz"
});
would be equivalent to
WeatherWidget.extend(Widget);
WeatherWidget.prototype.foo = 42;
WeatherWidget.prototype.bar = "baz";
You will still need to call the parent constructor explicitly in the child constructor, though; that part cannot reasonably be automated. But my Function.prototype.extend() adds a _super property to the Function instance which makes it easier:
function WeatherWidget (…)
{
WeatherWidget._super.apply(this, arguments);
}
Other people have implemented similar extensions.
According to some odd Javascript rules, new Widget actually invokes the constructor rather than returning a reference to the constructor. This question actually answers the question the difference between var a = new Widget() and var a = Widget().
In simple words, the new keyword tells Javascript to call the function Widget under a different set of rules than a regular function call. Going off the top of my head, the ones I remember are:
There is a brand new object created
Widget can use the this keyword to refer to that object.
If Widget does not return anything, this new object will be created.
This object will inherit a few additional properties that will indicate it was created by Widget that are used to track down property chains.
Without the new keyword, a call to widget would
If in strict mode, this will be set to undefined.
Otherwise, this will refer to the global object. (Called window by the browser.)
If the function does not return anything, then undefined will be returned.
Reference:
new keyword
WeatherWidget.prototype = new Widget;
does create a new instance of the Widget constructor and use it as WeatherWidget's prototype object. Using the new keyword creates the new object, sets up the inheritance chain of it to Widget.prototype, and applies the constructor function on it (where you can set up individual properties'n'methods, or create private-scoped variables).
Without the new keyword it would be an assignment of the Widget function to the prototype property - which does not make any sense. If you'd add the optional brackets (i.e. Widget()), it would invoke the function normally, but not as a constructor on a new instance, but with the global object as context. See also the reference for the this keyword.
Notice that you should not really use this code. As said, it creates a new instance by invoking the constructor function. But the purpose is only to create an empty object that inherits from the Widgets prototype object, not to instantiate something (which could do some harm, depending on the code). Instead, you should use Object.create (or its popular shim):
WeatherWidget.prototype = Object.create(Widget.prototype);
see also Javascript basic inheritance vs Crockford prototypical inheritance
In plain english you're extending one class with another. A prototype can only be an object so you set WeatherWidget's prototype to a new instance of Widget. If you removed the new keyword you would be setting the prototype to the literal constructor function which doesn't do anything.
var Appendages = function(){
this.legs = 2
};
var Features = function() {
this.ears = 4;
this.eyes = 1;
}
// Extend Features class with Appendages class.
Features.prototype = new Appendages;
var sara = new Features();
sara.legs;
// Returns 2.
Understanding that the prototype can be any object, something like this would also work:
var appendages = {
legs : 2
};
var Features = function() {
this.ears = 4;
this.eyes = 1;
}
// Extend Features class with Appendages class.
Features.prototype = appendages;
var sara = new Features();
sara.legs;
// Returns 2.
In JavaScript, if the key isn't found on the object, it checks the parents object you extended it from. Hence you can change items on the parent object on the fly like so:
var appendages = {
legs : 2
};
var Features = function() {
this.ears = 4;
this.eyes = 1;
}
// Extend Features class with Appendages class.
Features.prototype = appendages;
var sara = new Features();
sara.legs;
// Returns 2.
appendages.hair = true;
sara.hair;
// Returns true.
Note that this all happens during instantiation which means you can't just switch out the prototype after you've created the object:
var foo = {name : 'bob'};
var bar = {nachos : 'cheese'};
foo.prototype = bar;
foo.nachos;
// undefined
However, all modern browsers come with this newer __proto__ method, which allows you to do it:
var foo = {name : 'bob'};
var bar = {nachos : 'cheese'};
foo.__proto__ = bar;
foo.nachos
// "cheese"
Read up more on understanding JavaScript prototypes here.
This article from Pivotal Labs is also really good.
new is important for prototype inheritance; i.e.
Create a constructor with a method
var Obj = function(){};
Obj.prototype = {};
Obj.prototype.foo = function(){console.log('foo');};
Make a second constructor to extend the first with
var ExObj = function(){};
Now, if we prototype without new,
ExObj.prototype = Obj;
(new ExObj).foo(); // TypeError: Object #<Object> has no method 'foo'
Which means we haven't inherited from the prototype of Obj, however, if we prototype with new
ExObj.prototype = new Obj();
(new ExObj).foo(); // console logs 'foo'
Furthermore, adding new things to the prototype of ExObj doesn't make any changes to it's base, Obj.
JavaScript functions are "MULTIPLE(2) PERSONALITIES"!!!
They are regular-functions with input and output, which we call like function().
Also they are constructors of JS-objects, when we use the new keyword. >>>BUT<<< the new created objects are NOT INSTANCES of the constructors (like the objects of classes in class-based inheritance). The new objects are instances of the object of the prototype property of the constructor.
Then in WeatherWidget.prototype = you put the object you want to inherit its properties to the objects the constructor will create, which usually is new function() and not a function.
JavaScript created HUGE confusion in the programming community by naming the objects created by constructors, INSTANCES of them with the instanceof keyword.
> function f(){}
undefined
> new f() instanceof f
true

What are advantages to adding methods to a class vs adding methods to a class's prototype?

When I write a javascript class, its usually like this:
var myClass = function(prop1, prop2) {
this.prop1 = prop1;
this.prop2 = prop2;
this.method1 = function() {//blah}
this.method2 = function() {//blahblah}
}
But most books/tutorials I've read describe writing classes like this:
var myClass = function(prop1, prop2) {
this.prop1 = prop1;
this.prop2 = prop2;
}
myClass.prototype.method1 = function() {//blah}
myClass.prototype.method2 = function() {//blahblah}
What is the difference between these two approaches? Is one better than the other?
The second approach, using the prototype, is much more efficient if you create a large number of objects, and especially if you have a large number of methods.
The first approach requires all of the method functions to be created every time you call new myClass(). When you use the prototype these functions only have to be created once.
There is one advantage to the first approach: you can use your constructor function as a closure, so its methods have access to local variables in the constructor.
As a side note, your constructor function name should begin with a capital letter to follow normal JavaScript conventions.
What you implemented are just functions. They can be used as constructors for creating objects. When a constructor is invoked, a new object is created and it has its Prototype set to the constructor's prototype property, which means that it shares properties with constructor's prototype. In the first case method1 and method2 are properties of each object created using myClass constructor. If those methods are the same amongs all objects created that way, it is a kind of memory wasting. If you put those methods into constructor's prototype, no new copies of them will be created when constructor is invoked, but created objects would still have access to them using prototype chain. So it's generally for saving memory.

JavaScript inheritance: Object.create vs new

In JavaScript what is the difference between these two examples:
Prerequisite:
function SomeBaseClass(){
}
SomeBaseClass.prototype = {
doThis : function(){
},
doThat : function(){
}
}
Inheritance example A using Object.create:
function MyClass(){
}
MyClass.prototype = Object.create(SomeBaseClass.prototype);
Inheritance example B using the new keyword
function MyClass(){
}
MyClass.prototype = new SomeBaseClass();
Both examples seem to do the same thing. When would you chose one over the other?
An additional question:
Consider code in below link (line 15), where a reference to the the function's own constructor is stored in the prototype. Why is this useful?
https://github.com/mrdoob/three.js/blob/master/src/loaders/ImageLoader.js
Excerpt (if you don't want to open the link):
THREE.ImageLoader.prototype = {
constructor: THREE.ImageLoader
}
In your question you have mentioned that Both examples seem to do the same thing, It's not true at all, because
Your first example
function SomeBaseClass(){...}
SomeBaseClass.prototype = {
doThis : function(){...},
doThat : function(){...}
}
function MyClass(){...}
MyClass.prototype = Object.create(SomeBaseClass.prototype);
In this example, you are just inheriting SomeBaseClass' prototype but what if you have a property in your SomeBaseClass like
function SomeBaseClass(){
this.publicProperty='SomeValue';
}
and if you use it like
var obj=new MyClass();
console.log(obj.publicProperty); // undefined
​console.log(obj);​
The obj object won't have publicProperty property like in this example.
Your second example
MyClass.prototype = new SomeBaseClass();
It's executing the constructor function, making an instance of SomeBaseClass and inheriting the whole SomeBaseClass object. So, if you use
var obj=new MyClass();
console.log(obj.publicProperty); // SomeValue
console.log(obj);​
In this case its publicProperty property is also available to the obj object like in this example.
Since the Object.create is not available in some old browsers, in that case you can use
if(!Object.create)
{
Object.create=function(o){
function F(){}
F.prototype=o;
return new F();
}
}
Above code just adds Object.create function if it's not available so you can use Object.create function and I think the code above describes what Object.create actually does. Hope it'll help in some way.
Both examples seem to do the same thing.
That's true in your case.
When would you chose one over the other?
When SomeBaseClass has a function body, this would get executed with the new keyword. This usually is not intended - you only want to set up the prototype chain. In some cases it even could cause serious issues because you actually instantiate an object, whose private-scoped variables are shared by all MyClass instances as they inherit the same privileged methods. Other side effects are imaginable.
So, you should generally prefer Object.create. Yet, it is not supported in some legacy browsers; which is the reason you see the new-approach much too frequent as it often does no (obvious) harm. Also have a look at this answer.
The difference becomes obvious if you use Object.create() as it is intended. Actually, it does entirely hideout the prototype word from your code, it'll do the job under the hood. Using Object.create(), we can go like
var base = {
doThis : function(){
},
doThat : function(){
}
};
And then we can extend/inherit other objects from this
var myObject = Object.create( base );
// myObject will now link to "base" via the prototype chain internally
So this is another concept, a more "object oriented" way of inherting. There is no "constructor function" out of the box using Object.create() for instance. But of course you could just create and call a self defined constructor function within those objects.
One argument for using Object.create() is that it might look more natural to mix/*inherit* from other objects, than using Javascripts default way.
I am not an expert in java script but here is a simple example to understand difference between "Object.create" and "new" ..
step 1 : create the parent function with some properties and actions..
function Person() {
this.name = 'venkat';
this.address = 'dallas';
this.mobile='xxxxxxxxxx'
}
Person.prototype.func1 = function () {
return this.name + this.address;
}
step 2 : create a child function (PersonSalary) which extends above Person function using New keyword..
function PersonSalary() {
Person.call(this);
}
PersonSalary.prototype = new Person();
PersonSalary();
step 3 : create second child function (PersonLeaves) which extends above Person function using Object.create keyword..
function PersonLeaves() {
Person.call(this);
}
PersonLeaves.prototype = Object.create(Person.prototype);
PersonLeaves();
// Now check both child functions prototypes.
PersonSalary.prototype
PersonLeaves.prototype
both of these child functions will link to Person(parent function) prototype and can access it's methods but if you create child function using new it will return a brand new object with all parent properties which we don't need and also when you create any object or function using "New" that parent function is executed which we don't want to be.
Here are the takeaways
if you just want to delegate to some methods in parent function and don't want a new object to be created , using Object.create is best way.
A couple of additions to this answer set, mindful that JS obviously now has native classes:
In both Example A and Example B the static inheritance chain is not configured.
In Example B the superclass constructor is run at the "wrong time". It is run before the call to instantiate an instance of the subclass, before any arguments are known and perhaps before you have decided to instantiate an instance of the subclass. Note that constructors can contain any logic they like, including side-effectful logic, so this can be impactful.
Post-ES6 the inheritance chain can be configured in a standardised way using the class and extends keywords (which solve both of these issues).
See also.

Implementing instance methods/variables in prototypal inheritance

I've been playing around with prototypal inheritance after reading http://javascript.crockford.com/prototypal.html and having a bit of a problem with understanding how I could make use of it in the way I would use classical inheritance. Namely, all functions and variables inherited by the prototype essentially become statics unless they are overwritten by the child object. Consider this snippet:
var Depot = {
stockpile : [],
loadAmmo : function (ammoType) {
this.stockpile.push(ammoType);
}
};
var MissileDepot = Object.create(Depot);
var GunDepot = Object.create(Depot);
stockpile and loadAmmo definitely should be in the prototype, since both MissileDepot and GunDepot have them. Then we run:
MissileDepot.loadAmmo("ICBM");
MissileDepot.loadAmmo("Photon Torpedo");
alert(MissileDepot.stockpile); // outputs "ICBM,Photon Torpedo"
alert(GunDepot.stockpile); // outputs "ICBM,Photon Torpedo"
This is expected because Neither MissileDepot nor GunDepot actually have stockpile or loadAmmo in their objects, so javascript looks up the inheritance chain to their common ancestor.
Of course I could set GunDepot's stockpile manually and as expected, the interpreter no longer needs to look up the chain
GunDepot.stockpile = ["Super Nailgun", "Boomstick"];
alert(GunDepot.stockpile); // outputs "Super Nailgun,Boomstick"
But this is not what I want. If this were classical inheritance (say Java), loadAmmo would operate on MissileDepot and GunDepot's stockpile independently, as an instance method and an instance variable. I would like my prototype to declare stuff that's common to children, not shared by them.
So perhaps I'm completely misunderstanding the design principles behind prototypal inheritance, but I'm at a loss as how to achieve what I've just described. Any tips? Thanks in advance!
Javascript provides a way to do this the way U are used to :)
try this:
function Depot() {
this.stockpile = [],
this.loadAmmo = function (ammoType) {
this.stockpile.push(ammoType);
}
};
var MissileDepot = new Depot();
var GunDepot = new Depot();
MissileDepot.loadAmmo("ICBM");
MissileDepot.loadAmmo("Photon Torpedo");
alert(MissileDepot.stockpile); // outputs "ICBM,Photon Torpedo"
alert(GunDepot.stockpile); // outputs ""
And U can add the functions on the fly afterwards:
MissileDepot.blow = function(){alert('kaboom');}
Extending object with another object is also an option, but what You wanted is the fact, that OO programming in javascript is done by functions not objects with {} ;)
EDIT:
I feel bad for writing that without mentioning: The javascript "new" keyword is only for making it easier to OO veterans. Please, dig deeper into the prototypal inheritance and dynamic object creation as therein lies true magic! :)
For the method, all works as expected. It's just the fields that you need to take care of.
What I see a lot in YUI, is that the constructor allocates the instance varialbes. 'Classes' that inherit from a parent call the constructor of their parent. Look here:
http://developer.yahoo.com/yui/docs/DataSource.js.html
Example base class:
util.DataSourceBase = function(oLiveData, oConfigs) {
...
this.liveData = oLiveData;
... more initialization...
}
Example subclass:
util.FunctionDataSource = function(oLiveData, oConfigs) {
this.dataType = DS.TYPE_JSFUNCTION;
oLiveData = oLiveData || function() {};
util.FunctionDataSource.superclass.constructor.call(this, oLiveData, oConfigs);
};
// FunctionDataSource extends DataSourceBase
lang.extend(util.FunctionDataSource, util.DataSourceBase, {
...prototype of the subclass...
});
To achieve what you want, you need a cloning method. You don't want an inheritance prototype, you want a cloning prototype. Take a look at one of the Object.clone() functions already implemented, like prototypejs's one: http://api.prototypejs.org/language/object.html#clone-class_method
If you want to stick to some kind of prototyping, you have to implement an initialize() method that will give a stockpile property to your newly created Depots. That is the way prototypejs Classes are defined : a cloned prototype and an initialize() method : http://prototypejs.org/learn/class-inheritance
That's because you're trying to make a cat meow! Douglas Crockford is good, but that script you're using essentially works by looping through your parent object and copying all of its attributes into the prototype chain--which is not what you want. When you put things in the prototype chain, they're shared by all instances of that object--ideal for member functions, not ideal for data members, since you want each object instance to have its own collection of data members.
John Resig wrote a small script for simulating classical inheritance. You might want to check that out.
The secret to instance variables in JavaScript is that they are shared across methods defined in superclasses or from included modules. The language itself doesn't provide such a feature, and it may not be possible to mesh with Prototypal inheritance because each instance will need it's own instance variable capsule, but by using discipline and convention it is fairly straightforward to implement.
// Class Depot
function Depot(I) {
// JavaScript instance variables
I = I || {};
// Initialize default values
Object.reverseMerge(I, {
stockpile: []
});
return {
// Public loadAmmo method
loadAmmo: function(ammoType) {
I.stockpile.push(ammoType);
},
// Public getter for stockpile
stockpile: function() {
return I.stockpile;
}
};
}
// Create a couple of Depot instances
var missileDepot = Depot();
var gunDepot = Depot();
missileDepot.loadAmmo("ICBM");
missileDepot.loadAmmo("Photon Torpedo");
alert(missileDepot.stockpile()); // outputs "ICBM,Photon Torpedo"
alert(gunDepot.stockpile()); // outputs ""
// Class NonWeaponDepot
function NonWeaponDepot(I) {
I = I || {};
// Private method
function nonWeapon(ammoType) {
// returns true or false based on ammoType
}
// Make NonWeaponDepot a subclass of Depot and inherit it's methods
// Note how we pass in `I` to have shared instance variables
return Object.extend(Depot(I), {
loadAmmo: function(ammoType) {
if(nonWeapon(ammoType)) {
// Here I.stockpile is the same reference an in the Depot superclass
I.stockpile.push(ammoType);
}
}
});
}
var nonWeaponDepot = NonWeaponDepot();
nonWeaponDepot.loadAmmo("Nuclear Bombs");
alert(nonWeaponDepot.stockpile()); // outputs ""
And that's how to do instance variables in JavaScript. Another instance variable example using the same technique.

Categories