We are going to develop the following case:
-
Two classes:
-
Base: parent class with the same structure.
- State: color (string type, private scope).
- Behavior: sayColor, returning color.
-
Child: subclass from Base with:
- State: name (string type, private scope).
- Behavior: sayName, returning name.
-
Base: parent class with the same structure.
- Instanciating of child object.
If we use a “classical” OOP language like Java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
class Base{ private String color; public Base(String color){ this.color = color; } public sayColor(){ return color; } } class Child extend Base{ private String name; public Child(String color, String name){ super(color); this.name = name; } public sayName(){ return name; } } Child child = new Child("red", "Nicholas"); |
But if are using JavaScript the mechanism is quite different because in this language:
- Strictly speaking there are not classes.
- There is not an inherit mechanism base of “extend” keyword to create subclass.
Then, how could we accomplish this goal in JavaScript?
Masquerading
This approach consists of wrapping the “Base” function with the Child function, in this way:
- All states and functions defined inside Base function are copied into the Child function as a part of it.
- Accessing is completely controlled by means of Child function.
Object Masquerading
The implementation of this process follows the next steps:
- Create “Base” function.
- Start creation of “Child” function and defining an object variable to point the Base function. We can point to “Base” because functions in JavaScript are objects at the same time too.
- Call the Base function. Now we are invoking Base “constructor”, and we are generating a new “Base” object whose content is going to be integrated as part of Child function: masquerading Base function members (states & functions) inside Child function.
- Remove reference to Base function in order to avoid future modifications of Base via this reference.
- Add new members (states & functions) to child function later on delete the Base reference.Otherwise, you run the risk of overwriting the new properties and methods with those of the superclass.
Pros:
- Supporting multiple inheritance.
Cons:
- If we are using multiple inheritance with the classes Base1, Base2, and Child inheriting from the two previous ones (in this order), if Base1 and Base2 share members with the same name, we’re going to keep only the members from Base2, because of Base1 will be overwritten with the members of Base2.
We have two alternatives to masquerade the object:
- The Call() method.
- The Apply() method.
The call() method alternative.
Basically this alternative is very similar to object masquerading. But the process is simpler, because of using of call() method, produced in one line the masquerading process. So that, we don’t need the steps sequence:
- Base referencing,
- constructor invocation,
- and removing referencing.
1 2 3 4 5 6 7 8 9 10 |
function Child(aColor, aName) { // this.tmpMethod = Base; //this.tmpMethod(aColor); //delete this.tmpMethod; Base.call(this, sColor); // we need to pass in "this" to link Base members as part of Child, and the second parameter in order to pass in this.name = aName; this.sayName = function () { console.log(this.name); }; } |
“Base.call(this, sColor)” we have to highlight that about the arguments:
- Firstly: We need to pass in “this” in order to clone Base members as part of Child (masquerading).
- Secondly: passing the initialitation information to Base function. We can pass ONLY one parameter to construct Base.
The apply() method alternative
With this alternative, we are going to construct Base with more than one parameter. In order to we change the second argument from simple variable to array. Let’s see one example:
Prototype approaches
Any properties or methods on the prototype object will be passed on all instances of that class. Prototype chaining uses this functionality to accomplish inheritance.
Prototype chainning (pure)
With this technique, we load states and methods over the prototype object of the Base class.
Pros:
- The form of inheritance actually intended for use in ECMAScript is prototype chaining.
Cons:
- We create methods per class.
Revised thanks to
Alejandro García Iglesias.
Hybrid Constructor / Prototype chainning
But, how could we share methods among every instance, but have states per instance? The answer, by loading:
- States by construction functions.
- Methods over the prototype object.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
Base.prototype.sayColor = function () { alert(this.color); }; function Child(aColor, aName) { Base.call(this,aColor); // Masquerading "Base" states into Child this.name = aName; this.sayName = function () { alert(this.name); }; } Child.prototype = new Base(); // Here we inherit methods from Base prototype var objChild = new Child("red", "Nicholas"); objChild.sayName(); //output: "Nicholas" objChild.sayColor(); //output: "red" |
Pros:
- Use of parameterized constructor, so that we can store states per instance.
- Share methods among every instance of the same type of object.
Factory
This approach doesn’t create new objects by using “new” keyword but a factory function.
Functional inheritance
This is an alternative that doesn’t need to use “this” and “new” keyword inside the function factory.
Pros:
- Simplicity: a few steps are required to achieve inheritance .
- “this”-free: you don’t have to care with the context variable “this”, meaning that you can freely pass any method of a functional object as a callback parameter and everything will work as expected (see this script, for example) .
- Encapsulation: objects can have private (and even protected) members.
Cons:
- Performance: duplicated creation of methods per instance.
- Dynamism: you can’t add properties to the base class later on its definition.
- Reflection: Using of “instanceof” is not possible.
Functional inheritance – Example
Functional inheritance with function reference
This approach is one alternative to “functional inheritance” in order to avoid generating new copies of the same method per instance.
1 2 3 4 5 6 7 8 9 10 11 |
sayColor = function() { return 'The color is ' + base.color; }; function baseFactory(spec){ var base = {}; base.color = spec.color; base.showColor = function() { return 'The color is ' + base.color; }; return base; } |
Third parties JavaScript Inheritance libraries
All previous approaches need core JavaScript (ECMA) elements only. But there’re on the market a lot of libraries, not part of the ECMA specification, to accomplish the inheritance process. But we’re not going to analize this case, because these libraries deserve one different and large new post.
References
- Professional JavaScript for Web Developers – Nicholas C. Zakas.
- O’Reilly – JavaScript, The Definitive Guide 6th edition – David Flanagan.
- ECMA-262 definition, edition 5.1, rev. 6.
- JavaScript – Object Basics, by Satyen Pandya
- Functional inheritance vs prototypal inheritance – by Julien Richard-Foy.
- Elegant Code: Basic JavaScript: Prototypical Inheritance vs. Functional Inheritance.
-
Douglas Crockford – http://www.crockford.com/.
-
JavaScript, The Good Parts:
- Book – Functional inheritance, p52.
- Speech by Douglas Crockford.
-
JavaScript, The Good Parts:
- Private Members in JavaScript, by Douglas Crockford.
Let’s review some concepts.
> We can’t parameterize the creation of Base function so that we can’t create states per instance.
Not sure what you mean with that, but here i had modified your snippet to parameterize your Base constructor: http://jsbin.com/EbUJAcA/1/
As you can see, you have to add a “this.color = aColor” to the Child constructor, which, for modularity purposes you may not want to have in your Child object as your Base object is handling colors (but even that’s questionable because you’re already having a “aColor” parameter in your Child constructor). That’s why a hybrid constructor/prototype approach might appeal to some, but yours is having a problem: it calls the Base constructor twice. Here (http://jsbin.com/EbUJAcA/5/) i have fixed that changing the Child.prototype assignment to Child.prototype = Base.prototype;
And regarding your factory pattern, it’s not only non-performant for having duplicated method creation per instance, but also because you are in the “this-free” coolness, you’re constantly referencing the “spec” variable from called factory functions and that has to be kept in memory to be available for you when you call sayName() or sayColor() methods. Garbage collector can’t do anything to free memory from those calls. Here i have modified that to use “this” and fix this last problem: http://jsbin.com/oWUVUnod/1/
Also, you CAN have private members using prototypal inheritance: http://javascript.crockford.com/private.html
So i think that using a Factory like the one you’re describing is not worth it because the pros are not really the pros and all you have are cons which you don’t have in prototypal inheritance (which, as you truly say, is the intended form of doing inheritance by ECMAScript).
Best regards.
When you assign prototypes like this: Child.prototype = Base.prototype you have a singleton and it may have side effects so that has also some drawbacks.
I didn’t know that the garbage collector collect method calls, can you provide a link where I can read about it please?
“this” in JavaScript is a problem itself so if I can avoid it, I do it. Doing “var that = this;” is a hack to doesn’t really solve the problem.
I definitely prefer the “factory” or “functional inheritance” as Douglas call it for “classes” where only one or a few instances are going to be created.
Thanks
Hey Carlos, thanks for your comments.
Can you tell which kinds of side effects? If you check on this version of my code i added the following statements at the bottom:
And the result is that
objChild
is indeed an instance ofChild
andBase
(Base
too because it’s in the prototype) because i called theBase
constructor on theChild
constructor for the new instance. This is the same result as doing:Check it out for yourself. If you think i’m misunderstanding what do you mean with singleton then explain further.
Memory is allocated for all objects (objects, speaking in this context, include function scopes). I’ll copy the questioned code sample:
What happens is you’re returning
base
from the factory andbase
has asayColor
property referencing to a function. Inside of that function you reference to thebase
variable from the parent scope (that is called a closure). So the parent scope object with abase
property has to be preserved (ie, non-collected) to be available for when you callbase.sayColor
. More info on memory management and the closure memory leak pattern.this
is not a problem by itself (the only ugly thing is it’s name) if you know how to use it (it can be tricky at first, yes). It’s a very powerful trick and allows things like creating functions that can work on different execution contexts (ie, different “this-es”). You just have to know how it works.I can’t tell you what works for you, but i do have to tell you to be aware of performance problems like the ones mentioned before. On the other hand, as has been said before, prototypal inheritance is the way it was meant to work with inheritance on the language. You can make some wrapper on top of that to make it look nicer to your eyes (as Doug does nowadays), but even then, you are working with constructors and prototypes inside of your wrapper, and that’s a good thing.
I hope i’ve clarified some aspects and let me know if you have further questions or spotted any errors.
Best.
There are some links in my comment, but the links style in this blog is the same color as regular text, or at least thats what Disqus detects and applies. Look for the hand cursor. Cheers.
Thanks for your comprehensive explanation and the video. This video series on JS by Douglas are on my to-do list, I’ve seen only 2 of them.
Now, what I mean with the prototype is this:
—————–
function Base(){}
Base.prototype.methodA = function(){
console.log(‘say A’);
}
function Child(){ Base.call(this); }
Child.prototype = Base.prototype;
Child.prototype.methodB = function(){
console.log(‘say B’);
}
var base = new Base();
base.methodB(); // does it really make sense to have this method here?
————
The thing is that methodB was defined in the child class, it doesn’t make sense to have it also in the parent class and all the subclasses of base.
Regarding the garbage collection, I understand what you say. As I said before I use the functional style for classes which are going to serve for just one instance or just a few instances. In this case memory is not a problem.
In the case of entities and value objects where I can have many objects in memory, then performance and memory can be a problem.
First of all, thanks to both Alejandro and Carlos for your comments
Let’s go step by step.
* Prototype approach.
True, there were some issues in the previous code. Now they’re solved.
The code currently represents an example of “pure” prototype approach. Within this approach, it doesn’t make much sense using parameters with Base constructor, because in case you used them they’d have to be initialized inside the constructor.
(Professional JavaScript for Web Developers, by Nicholas C. Zakas, p 109, note about parameters into the Base constructor call)
* Private members.
According to Crockford’s post you commented previously, I think that private members are related to Constructors, not to Prototypes:
– “Private members are made by the constructor.” – Title: Private.
Concretely Crockford speaks about two types of private members:
– Variables: They are attached to the object, but they are not accessible to the outside it, nor are they accessible to the object’s own public methods. They are accessible to private methods.
– Methods: Or a privileged method which is able to access the private variables and methods, and is itself accessible from the public methods and from outside. It is possible to delete or replace a privileged method, but it is not possible to alter it, or to force it to give up its secrets. Privileged methods are assigned with this within the constructor.
* Factory inheritance.
I’ve discovered this approach recently. For this reason I prefer to experiment with this more before recommending or not its use. Anyway I think it’s interesting to know about this method, specially if Douglas Crockford is behind it.
In addition I think the “this” pro commented by Carlos is also interesting.
Child.prototype = new Base() vs Child.prototype = Base.prototype
I follow the way proposed by Nicholas C. Zakas:
– Child.prototype = new Base()
I didn’t know the singleton question with “Child.prototype = Base.prototype”.
But, I think it would be interesting to experiment and compare both points (with “new” and without).
(Professional JavaScript for Web Developers, by Nicholas C. Zakas, p 109)
* About the color links style of the comments , I agree. I’ll revise the Disqus setup to change this color.
Thanks for your comments and your effort. I’m totally sure this kind of discussions are a excellent way to improve and learn.