Inheritance approaches in JavaScript

By | 19 November, 2013

We are going to develop the following case:

Child class extends class Base - UML

  • 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.
  • Instanciating of child object.

If we use a “classical” OOP language like Java:

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?

JavaScript Inhertiance - Approaches

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:

  1. Create “Base” function.
  2. 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.
  3. 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.
  4. Remove reference to Base function in order to avoid future modifications of Base via this reference.
  5. 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.

Object-Masquerading-ProcessObject Masquerading – Example

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:

  1. Base referencing,
  2. constructor invocation,
  3. and removing referencing.

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:

JS Bin

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.

Prototype chainning – Example

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.

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.

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

6 thoughts on “Inheritance approaches in JavaScript

  1. Alejandro Iglesias

    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.

    Reply
    1. Carlos Ble

      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

      Reply
      1. Alejandro Iglesias

        Hey Carlos, thanks for your comments.

        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.

        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 of Child and Base (Base too because it’s in the prototype) because i called the Base constructor on the Child 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.

        I didn’t know that the garbage collector collect method calls, can you provide a link where I can read about it please?

        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 and base has a sayColor property referencing to a function. Inside of that function you reference to the base variable from the parent scope (that is called a closure). So the parent scope object with a base property has to be preserved (ie, non-collected) to be available for when you call base.sayColor. More info on memory management and the closure memory leak pattern.

        “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.

        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 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.

        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.

        Reply
        1. Alejandro Iglesias

          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.

          Reply
        2. Carlos Ble

          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.

          Reply
    2. Nico Cortés

      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.

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *