JS Inheritance and mutating prototype - javascript

AFAIK, JS provides inheriatnce by means of assigning a prototype chain to a newly created object. So, the code below seems to be the correct way to me:
function Animal(name){
this.name = name;
}
Animal.prototype.getName = function(){return this.name;};
function Cat(){
Animal.apply(this, arguments);
}
Cat.prototype = Object.create(Animal.prototype);
Cat.prototype.constructor = Cat;
Cat.prototype.sayHi = function(){return 'Hi, my name is '+this.name+', and I am a "'+this.constructor.name+'" instance';};
Is this actually correct? And, I've read, that mutating object's prototype is a slow discouraged operation, that affects all the later calls to it. But here we've just mutated Animal.prototype and Cat.prototype. So, is that bad? If it is how do we deal with it? Or I've misunderstood something about that prototype mutating warning? If so, what does it actually mean?

Is this actually correct?
In that it doesn't contain anything that might be considered poor practice, yes. Whether it's correct in terms of the outcome being what you expected can't be determined.
And, I've read, that mutating object's prototype is a slow discouraged operation,
I have no idea what that means. However, it's not considered good practice to modify objects you don't own, so don't go messing with built–in or host objects (there are many articles on why not, e.g. What's wrong with extending the DOM and Extending builtin natives. Evil or not?).
that affects all the later calls to it.
Modifying a prototype may affect all objects that have it as their [[Prototype]], that's the point of prototype inheritance.
But here we've just mutated Animal.prototype and Cat.prototype. So, is that bad?
Of itself, no. If it achieves the outcome you require, then fine. You're defining the constructor, prototype properties and inheritance scheme, so it's up to you. There might be more efficient or more easily maintained schemes, but that's another topic.
Comment
Complex inheritance schemes are rarely useful in javascript, there just isn't much call for it. Most built–in objects have only one or two levels of inheritance (e.g. function instances inherit from Function.prototype and Object.prototype). Host objects (e.g. DOM elements) may have longer chains, but that is for convenience and not really necessary (at least one very popular browser didn't implement prototype inheritance for host objects until recently).

You're on the right track. You don't want to mutate Animal's prototype because that breaks the concept of inheritance. As was mentioned in the comments, using Object.create() is the correct way to inherit properties and methods from one object to another. A simple example of prototypical inheritance, using your example, is achieved this way:
function Animal(name) {
this.name = name;
}
Animal.prototype = {
getName: function() {
return this.name;
}
};
function Cat(name, color) {
Animal.call(this, name);
this.color = color;
}
Cat.prototype = Object.create(Animal.prototype);
Cat.prototype.constructor = Cat;
Cat.prototype.getColor = function() {
return this.color;
};
var animal = new Animal('Bob');
var cat = new Cat('Tabby', 'black');
console.log(cat.getName());
console.log(cat.getColor());
console.log(animal.getName());
console.log(animal.getColor()); // throws an error

Hi inheritance in JavaScript is rather complex and you will have to have a good understanding of the prototype object. Ill suggest you use the inheritance pattern of for instance TypeScript. You can give it a try on the Playground
Take a look at this:
var extends = this.extends || function (class, parent) {
for (var property in parent) {
if (parent.hasOwnProperty(property)) {
class[property] = parent[property];
}
}
function newClass() {
this.constructor = class;
}
newClass.prototype = parent.prototype;
class.prototype = new newClass();
};
var Animal = (function () {
function Animal(name) {
this.name = name;
}
return Animal;
})();
var Cat = (function (_super) {
extends(Cat, _super);
function Cat(name) {
_super.call(this, name);
}
Cat.prototype.sayHi = function () {
return "Hello my name is:" + this.name;
};
return Cat;
})(Animal);

You seem to be mixing the prototype property of functions with the internal [[proto]] property of all objects (including functions). They are two distinct things.
Mutating the internal [[proto]] property of an object is discouraged. This can be done either via setPrototypeOf or via the __proto__ accessor, which is inherited from Object.prototype:
var a = {}; // `a` inherits directly from `Object.prototype`
var b = {}; // `b` inherits directly from `Object.prototype`
a.__proto__ = b; // `a` now inherits directly from `b`
// or
Object.setPrototypeOf(a, b); // `a` now inherits directly from `b`
This is what is discouraged, mutating the internal [[proto]] property of an object after it has been created. However, it should be noted that while the object is being created it's alright to assign any object as its internal [[proto]] property.
For example, many JavaScript programmers wish to create functions which inherit from some object other than Function.prototype. This is currently only possible by mutating the internal [[proto]] property of a function after it has been created. However, in ES6 you will be able to assign the internal [[proto]] property of an object when it is created (thus avoiding the problem of mutating the internal [[proto]] property of the object).
For example, consider this bad code:
var callbackFunctionPrototype = {
describe: function () {
alert("This is a callback.");
}
};
var callback = function () {
alert("Hello World!");
};
callback.__proto__ = callbackFunctionPrototype; // mutating [[proto]]
callback.describe();
It can be rewritten in ES6 as follows:
var callbackFunctionPrototype = {
describe: function () {
alert("This is a callback.");
}
};
// assigning [[proto]] at the time of creation, no mutation
var callback = callbackFunctionPrototype <| function () {
alert("Hello World!");
};
callback.describe();
So, mutating the internal [[proto]] property of an object (using either setPrototypeOf or the __proto__ accessor) is bad. However, modifying the prototype property of a function is fine.
The prototype property of a function (let's call the function F) only affects the objects created by new F. For example:
var myPrototype = {
describe: function () {
alert("My own prototype.");
}
};
function F() {}
var a = new F; // inherits from the default `F.prototype`
alert(a.constructor === F); // true - inherited from `F.prototype`
F.prototype = myPrototype; // not mutating the `[[proto]]` of any object
var b = new F; // inherits from the new `F.prototype` (i.e. `myPrototype`)
b.describe();
To know more about inheritance in JavaScript read the answer to the following question:
JavaScript inheritance and the constructor property
Hope that helps.

Related

Javascript Prototype and inheritance

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/

hasOwnProperty returns true, when checked against parent object properties

My JavaScript code:
console.clear();
function BaseClass(nname) {
var name = nname;
this.bc_PublicProperty = "DefaultValue_BaseClass";
this.bc_getName = function GetName() {
return name;
};
this.bc_setName = function SetName(nname) {
name = nname;
};
}
function SubClass(nname) {
BaseClass.call(this, nname);
this.sc_PublicProperty = "DefaultValue_SubClass";
this.sc_getName = function GetName() {
return name;
};
this.sc_setName = function SetName(nname) {
name = nname;
};
}
SubClass.prototype = Object.create(BaseClass.prototype);
SubClass.prototype.constructor = SubClass;
var bc = new BaseClass("Anton");
var sc = new SubClass("Bernd");
console.log("hasOwnProperty check on subclass object 'sc' returns true for Method 'bc_getName'");
for (var pro in sc) {
console.log("Is " + pro + " own property of subclass: --> " + Object.hasOwnProperty.call(sc, pro));
}
I have two objects (BaseClass and SubClass). One inherits from the other using the constructor pattern, as explained on MDN.
Now, when I iterate over all properties of the subclass object, they all return true for hasOwnProperty, even for the parent methods/properties, except constructor.
Does it mean, that it breaks when using the constructor pattern?
When I put public properties and methods in the constructor function, whether in BaseClass or SubClass, they will always be "marked" as own properties/methods. When I instead attach them to the respective prototype, the hasOwnProperty will output "false" for them.
Whether you put the public methods/properties to the prototype or to the constructor function itself, they will all be available for use in the subClass (--> SubClass2, --> SubClass3).
The only thing, that I can think of right now, why you should attach them to the prototype object, is because of efficiency reasons, as explained here, "Defining class methods"-section. In order not to add closures for every constructed instance.
Value Types should be declared on the prototype, but not for instance variables whose initial values are dependent on arguments to the constructor, or some other state at time of construction.
You can override both properties/functions irrespective of their place of declaration.
Also setting up getters and setters on the prototype, for instance to set or get a private variable, makes no sense, as the private variable has to be public, in order to be accessible by the getters and setters attached to the prototype.
Therefore it makes no sense to use getters and setters. You can access the public variable directly.
I have to adjust my question a bit now:
When do I need hasOwnProperty, if actually public props/functions should be declared on the prototype, which in turn will all output Object.hasOwnProperty(obj,"prop/func") --> false. Give me a use case, when it makes sense, to use hasOwnProperty.
console.clear();
var l = function(v) {
console.log(v);
};
function BaseClass(nname) {
this.bc_nameProp = nname;
this.bc_ownFunc = function() {
l("bc_ownFunc of BaseClass called");
};
this.bc_getName = function GetName() {
return this.bc_nameProp;
};
}
BaseClass.prototype.bc_getName = function GetName() {
return this.bc_nameProp;
};
BaseClass.prototype.bc_PublicProperty = "DefaultValue_BaseClass";
BaseClass.prototype.bc_setName = function SetName(nname) {
bc_nameProp = nname;
};
function SubClass(nname) {
BaseClass.call(this, nname);
this.sc_setName = function SetName(nname) {
bc_nameProp = nname;
};
this.bc_getName = function GetName() {
return "xyz";
};
}
SubClass.prototype = Object.create(BaseClass.prototype);
SubClass.prototype.constructor = SubClass;
SubClass.prototype.sc_getName = function GetName() {
return this.bc_nameProp;
};
SubClass.prototype.sc_PublicProperty = "DefaultValue_SubClass";
var bc = new BaseClass("Anton");
var sc = new SubClass("Bernd");
l("----- iterating over BaseClass properties ------");
l("");
for (var pro in bc) {
l("Is " + pro + " own property of BaseClass: --> " + Object.hasOwnProperty.call(bc, pro));
}
l("");
l("----- iterating over SubClass properties ------");
l("");
for (var p in sc) {
l("Is " + p + " own property of subclass: --> " + Object.hasOwnProperty.call(sc, p));
}
l(bc.bc_getName());
l(sc.bc_getName());
l(sc.sc_getName());
Solution
When I asked this question, I was of the opinion, that when using classical inheritance in JavaScript, I can differentiate which properties/functions of my subclass directly belong to it, using hasOwnProperty. Which is not possible, as all the properties/functions of the parent prototype are copied to the prototype of the SubClass:
SubClass.prototype = Object.create(BaseClass.prototype);
All properties/functions attached to prototypes return "false", when using hasOwnProperty.
And if you have public properties/functions declared in the constructor functions of BaseClass and SubClass, all these properties return "true", when calling hasOwnProperty for these properties on the subclass.
These are copied to the SubClass using this statement:
BaseClass.call(this, nname);
So using hasOwnProperty while iterating over all properties of an obj of type SubClass, will output false for all properties/functions declared on prototype level and true for all properties/functions declared on constructor function level.
Now, I understand why using hasOwnProperty in this use case makes no sense.
Check that you're calling BaseClass.call(this) on SubClass's constructor, meaning that you're adding BaseClass properties and functions to the SubClass instance, because this is an instance of SubClass.
This is why hasOwnProperty returns true for all properties.
Wrong prototypes...
At the end of the day, you're not taking advantage of prototypes in JavaScript.
Functions that must be part of any instance of some prototype should be defined in the prototype itself.
var A = function() {};
A.prototype = {
doStuff: function() {}
};
Actually, the only benefit of defining functions during construction-time is that you ensure that an object will always define some functions/properties, but you're ensuring this once the object has been already created.
For me, there's a very small difference between the following ways of defining properties:
var A = function() {};
var instance = new A();
instance.text = "Hello, World!";
// or...
var A = function() {
this.text = "Hello, World!";
};
var instance = new A();
The first code sample defines a text property after the constructor has been called while the second one does it inside the constructor, but in both cases either this or instance are references to the same object (i.e. the instance of A).
With prototypes you ensure that all objects created from some constructor function will share the same members, and these members will be inherited and consumed using prototype chain.
About the OP's update...
The OP said a lot of things, but summarizing said:
[...] I have to adjust my question a bit now: When do I need
hasOwnProperty, if actually public props/functions should be declared
on the prototype, which in turn will all output
Object.hasOwnProperty(obj,"prop/func") --> false. Give me a use case,
when it makes sense, to use hasOwnProperty.
You're going in the wrong way... Why asking yourself when you need hasOwnProperty? Ask yourself when you need simple objects with less reusability or when you need actual reusability. hasOwnProperty has nothing to do with this issue.
When you use a literal object (i.e. ones declared as is with {} syntax)? When you need dictionaries, argument maps, value objects... Here you like hasOwnProperty because usually your code receiving arguments will look like this:
function X(uri, options) {
if(typeof options != "undefined") {
// For example, we set a default value if options has no
// mimeType property...
options.mimeType = options.hasOwnProperty("mimeType") ? options.mimeType : "application/json";
}
}
When do you use complex objects using prototypes? When you define behavior and you need to reuse it across your application or even multiple applications, and also you need to add more behavior on top of generic requirements (hello inheritance).
About why using hasOwnProperty...
The OP said:
But why would you use "hasOwnProperty" here, if you want to check the
existence of an property? Shouldn't it be: options.mimeType =
options.mimeType || "application/json";
There's a lot of code on the Internet doing the `options.mimeType =
options.mimeType || "application/json", right, because in JavaScript undefinedevaluates tofalse(ifoptionsdoesn't own amimeTypeproperty returnsundefined`).
In my humble opinion, I would use hasOwnProperty because it returns a boolean either if it exists or it exists and it has undefined as the value.
For example, options could be defined as { mimeType: undefined } and sometimes you want to know if the property exists even if it has undefined as value. The undefined as false treats the case of if it's undefined, either if it exists or not, do X, and hasOwnProperty is I want to be sure it has the property or not.
So why would I use options.hasOwnProperty over other approaches?. Easy: because, since language gives a tool to verify if a property exists in some object, why do I need a trick? object.hasOwnProperty returns true or false, and I'm sure the property exists or not, even if the property has undefined value.
With options.hasOwnProperty("mimeType") I can throw an Error if it exists and it has an undefined value. Why do I prefer this? Because I like the fail-fast concept: if you gave me the property with undefined value I tend to think that there's some bug in your code. Define it or not, my friend!
I'm going to assume by "constructor" pattern, you mean assigning this.fn = function (){}; and this.val = true; in the constructor function.
The this in the context of the BaseClass.call is changed to be the sub class, so all assignments within that are made on the sub class itself. Strictly speaking this isn't actually doing any sort of inheritance at all. Let me explain a bit in the code.
SubClass.prototype = Object.create(BaseClass.prototype);
In this line, you would be inheriting the prototype of the BaseClass on the sub class, which would ordinarily mean inheritance. However, the prototype for the BaseClass is the exact same prototype of the Function object, which the SubClass was already inheriting from. The this.___ assignments do not add to the prototype of an object, only to an instance of that object. To add to the prototype, you would need to do something along the lines of BaseClass.prototype.___ = 'foo'; However, you don't want to do that in the constructor, as that assignment is then happening every time you create a new object.
Also, in your code, calling SubClass.getName will throw an error. name is not defined in that context, only in the BaseClass context.

JavaScript prototype-Object - how to access inheritance

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

Confuse about prototype inheritance in javascript

I want to achieve a extend method on a constructor function, and use it to initialize an instance, like:
var view_instance = View.extend()
so I tried this:
define(function (require, exports, module) {
function View(size, color) {
this.size = size;
this.color = color;
};
View.prototype = {
show: function () {
console.log("This is view show");
}
}
View.extend = function (props) {
var tmp = new this("12", "red");
console.log(this);
console.log(tmp instanceof this) //true
console.log(tmp.prototype); //undefined!
return tmp
}
return View;
})
in the above extend method, I initialize an instance through new this(), but I can't log its prototype, and I check the this is right.
So what's wrong with my code? Why the prototype disappear? How can I do it right?
There's nothing wrong with your code. It does what it's supposed to do. The prototype property only exists on functions.
When you precede a function call with the new keyword JavaScript creates an object which inherits from the prototype of the constructor.
To put it in simple terms:
function F() {} // we have a constructor
var o = new F; // we create an instance
console.log(Object.getPrototypeOf(o) === F.prototype); // o inherits from
// F.prototype
Objects in JavaScript inherit from other objects via delegation. This means say we try to access a property on the object o which we saw above:
JavaScript will first try to find the property on o itself.
If it can't find the property on o then it will try to find it on Object.getPrototypeOf(o) (or to put it more succinctly o.__proto__). The prototype of o is F.prototype.
If it can't find the property on F.prototype then it will try to find it on F.prototype.__proto__ which is Object.prototype.
If it can't find the property on Object.prototype then it will give up because Object.prototype.__proto__ is null.
That is prototypal inheritance for you in a nutshell.
The reason your code logs undefined for tmp.prototype is because tmp doesn't have any property called prototype. Only functions have a prototype property. Try this instead:
console.log(Object.getPrototypeOf(tmp));
The above is the same as the following. However the __proto__ property of objects is deprecated. Use it at your own risk:
console.log(tmp.__proto__);
If you want to learn more about inheritance then read the following articles:
Aadit M Shah | Why Prototypal Inheritance Matters
JavaScript inheritance and the constructor property - Stack Overflow
tmp.constructor.prototype is what you want. o.__proto__ is just a shortcut for o.constructor.prototype and it's non-standard.
[EDIT]
You can see the figure in this question. It shows that Foo.prototype.constructor points to Foo itself. However, since you are overwriting the prototype of the constructor with the line View.prototype = {...}, View.prototype.constructor will be function Object() { [native code] } instead of View itself. So a more accurate way would be assigning properties to the original prototype directly or overwriting it with the constructor property set manually:
// Assign properties to the original prototype to prevent overwriting the `constructor` properties.
View.prototype.show = function() {};
// Or set the constructor manually.
View.prototype = {
show: function() {},
constructor: View
};
The prototype property belongs to constructors. The instances have a non-standard __proto__ property pointing to the same object. So:
console.log(tmp.__proto__);
Or:
console.log(Object.getPrototypeOf(tmp));

why do we use `Boy.prototype = new Human;` to simulate inheritance?

i don't get why everyone is using Boy.prototype = new Human; to simulate inheritance. Look, what we want is the function's of A right? we can do that without instantiating a new A (in fact instantiating a new A does give us undesirable results, in the sense that we are actually running the instantiating function which isn't what we want)
So isn't this a better solution?
for (var prop_name in Human.prototype) {
Object.defineProperty(
Boy.prototype,
prop_name,
Object.getOwnPropertyDescriptor(Human.prototype,prop_name)
);
}
Say we are that particular and want not only the enumerable properties in Human.prototype we could still achieve it by using Object.getOwnPropertyNames and calling it on the prototype chain, which in turn is available to us through Object.getPrototypeOf.
So what exactly is the benefit of doing Boy.prototype = new Human; to simulate inheritance when we have better options available to us?
A better option is to create an intermediate to hold the prototype.
function extend(clazz, superclass) {
var intermediate = function() {};
intermediate.prototype = superclass.prototype;
clazz.prototype = new intermediate();
// Following line is optional, but useful
clazz.prototype.constructor = clazz;
}
This avoids unnecessary copying, but still means that you don't need to instantiate an object that will do work in its constructor. It also sets up the prototype chain so that you can use instanceof. It also doesn't result in superclass prototype contamination which some inheritance antipatterns can.
For completeness, your subclass should call the superclass constructor in its constructor, which you can do with Superclass.call(this);.
EDIT: Since ES5, you can replace calls to extend with
Subclass.prototype = Object.create(Superclass.prototype);
which does the same thing.
It sets up the prototype chain correctly, meaning that instanceof and isPrototypeOf() will work
It's less verbose
There are simple but ugly workarounds to prevent a constructor function from performing its usual initialization when you're just using it to create a prototype object. For example, you could either check the arguments:
function Boy(name) {
if (arguments.length == 1) {
this.name = name;
// Do other initialization
}
}
... or move the initialization into a separate method that has to be called explicitly:
function Boy(name) {}
Boy.prototype.init = function(name) {
this.name = name;
// Do other initialization
}
This has the obvious downside of requiring you to remember to call init() whenever you create a new Boy.
In ECMAScript 5 environments (current versions of most browsers, for example), a better option may be ECMAScript 5's Object.create(), which allows you to create an object which inherits directly from another object and sets up the prototype chain for you. This can be emulated (but only approximately: see Object.defineProperty in ES5?) in non-ES5 environments:
if (!Object.create) {
Object.create = function(o) {
function F() {}
F.prototype = o;
return new F();
};
}

Categories