Reputation: 44285
I have a fiddle to help me in my understanding of JavaScript prototyping and inheritance. The comments tell the story.
//From Douglas Crockford's "Javascript: the good parts": a helper to hide the "ugliness" of setting up a prototype
Function.prototype.method = function(name,func) {
this.prototype[name] = func;
return this;
}
function SomeFunc(value) {
this.setValue(value);
}
//Inherit the function (to me this conceptually the same as adding a member to a class)
SomeFunc.method('setValue', function (value) {
this.value = value;
return this;
});
try
{
SomeFunc(1);
}
catch(e)
{
alert(e);
}
Why do I get an exception? Are my notes correct in that what JavaScript calls inheritance is to a Classical programmer simply adding a new member to a class? What is the difference between augmentation and inheritance?
Upvotes: 0
Views: 2199
Reputation: 816760
Are my notes correct in that what JavaScript calls inheritance is to a Classical programmer simply adding a new member to a class?
No, not really. In JavaScript, we have prototype-based inheritance. That means an object has a reference to another certain object, its prototype. Whenever a property of an object is accessed, the prototype chain is searched for this property. So if the the object does not have this property itself, its prototype is inspected for this property and so on.
+------------+ +-------------+
| Instance | | Prototype |
| __proto__ -+--->| __proto__ -+-->...
| foo | | bar |
+------------+ +-------------+
Instance
has both, the foo
and bar
properties.
Now, if you have a constructor function, you can create many instances (objects) referring to the same prototype. When you now add a new property to that prototype, all instances will have this property too (due to the prototype chain).
This is often done to dynamically extend instances but it is only one consequence of prototype inheritance, it is not inheritance itself.
What is the difference between augmentation and inheritance?
Inheritance would be to set the prototype of an object to a certain object so that it is in the prototype chain. Augmentation is just copying properties. The object would own that property then:
+------------+
| Instance |
| __proto__ -+--->...
| foo |
| bar |
+------------+
Why do I get an exception?
Because you are calling SomeFunc
like a "normal" function, not like a constructor function. In that case, this
will refer to window
, which does not have a setValue
method.
Instead you want to call it with the new
operator [MDN], to create a new instance:
var instance = new SomeFunc(1);
If called this way, this
will refer to an empty object which inherits from the constructor function's prototype
property (SomeFunc.prototype
).
MDN has a nice article about this
and what it refers to in certain situations.
And if you look at what method
is doing, you see that it adds a new property to SomeFunc.prototype
(this
refers to SomeFunc
):
this.prototype[name] = func;
In fact, was the first part of your code is doing is what I mentioned above: By extending Function.prototype
, you add a new property to each function and this lets you call SomeFunc.methods
later.
Further reading:
this
Upvotes: 5
Reputation: 9050
try instead:
new SomeFunc(1);
because this is the case when prototype works
Upvotes: 0