Defining Classes and Objects in JavaScript

By | 12 November, 2013

We’d like to create one new object “Car” in JavaScript with the same features:

  • oCar objectproperty / state: color
  • method: showColor

One way to create your own objects in JavaScript instancing from JavaScript Object:

But so that we have a trouble: we can’t reuse the same structure (states & methods) to generate new oCar objects

How could we solve this issue?

Car class -> object car

  • We need to define a pattern containing states and methods,
  • and reuse it later to create new “car” object (instanciation process).

We need a reusable pattern. Maybe, we need a “class”.

For instance, if we’re coding in Java:

But the problem in JavaScript is:

Strictly speaking, JavaScript doesn’t have classes.

So, what could we do?

Defining Classes and Objects - Mechanims

Factory paradigm

We can create a “factory function” and assign it the process to:

  • create the structure: states and methods.
  • Initialize states.
  • Return the new create object

Now we can use this factory function to create new car objects

Problems:

  • We are not using the recomended ECMA operator “new”. And we aren’t going to use the “intanceof” operator to detect if a object is an instance of “Car”.
  • Performance: the factory function creates both states as methods for each new instace. Maybe states are particulars for each instance. But it doesn’t make any sense to create a new method each time, because this behaviour is shared among every instance.

Factory paradigm with function reference.

In order to avoid the performance issue we could:

  • define methods outside the factory function.
  • And inside of factory function assign to method, a reference of the previous method defined

But the lack of using new operator (and his consequences) remains.

Hybrid factory paradigm

This is a possible wayaround when the dynamic don’t work.

Downsides

  • Can’t use instanceof operator to detect Car objects.
  • Same memory management problem that factory function.

Functional inheritance

This is an alternative that doesn’t need use “this” and “new” keyword inside the function factory.

Upsides:

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

Downsides:

  • 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

(Provided by Carlos Blé & @pasku1. Thanks to Julien Richard-Foy)

 

Constructor paradigm

We could use the constructor function:

  • Defining: the “class” structure inside the constructor function and initialize its states.
  • Intanciation: using the constructor function by new operator to create new “Car” objects.

  • Upsides:
    • Using new operator
  • Downsides.
    • Perfomance: recreating methods per instance

Prototype paradigm

We could use the prototype property:

  • Defining an empty constructor function.
  • Assign states and methods to the Car via its prototype.
  • Finaly, instance cars by new operator.

  • Upsides:
    • Using new operator
    • Perfomance: methods shared amongs every instance of the class
  • Downsides.
    • Sharing states among every instance, because of we couldn’t have diferents values of thesse states in diferents instances.
    • We can’t initialize states from the contruction process.

Hybrid constructor/prototype paradigm

Is there any way to fix all the previous issues?. Yes, there’s. We can combine both constructor as prototype feature:

  • Defining:
    • states inside the constructor and initialize them.
    • Mehods by prototype of the class and assign them behaviours.
  • Instaciating objects by new operator.

  • Using new operator
  • Sharing states.
  • Reusing methods.

Maybe, the only issue people from classical OOP can consider is: states and methods are defined in diferents places.

Dynamic prototype method

In order to “unify” the creation process of the structure to put closer to the “traditional” OOP approach we could follow the same process of hybrid contructor / paradigm, but:

  • Defining the methods inside the constructor by prototype, if methods was not initilize previously (if (typeof Car._initialized == “undefined”)).
  • Later, we don’t forget mark the prototype as initilize (Car._initialized = true;)

  • Upsides:
    • Traditional visual OOP class defining. But this a style question. Up to your preferences.

References:

  • Profesional JavaScript for Web Developers – Nicholas C. Zakas.
  • Oreally – JavaScript, The Definitive Guide 6th edition – David Flanagan.
  • ECMA-262 definition, edition 5.1, rev. 6.
  • http://www.slideshare.net/satyenpandya/javascript-object-basics.
  • JavaScript The Good Parts, functional inheritance – Crockford (suggested by Carlos Blé).
  • Functional inheritance vs prototypal inheritance – by Julien Richard-Foy.

5 thoughts on “Defining Classes and Objects in JavaScript

  1. Carlos Ble

    Nice post Nico. I prefer the kind of “factory” way, named “functional inheritance” by Crockford in “JavaScript The Good Parts”

    function car(){
    var self = {};

    var color = “green”
    self.showColor = function(){
    return alert(color);
    }
    return self;
    }

    This saves me from trouble with the “this” and “new” keyword, but not using them at all. It provides me a way to have private and protected members.

    Reply
    1. cogani Post author

      Thanks a lot for your comment, Carlos.
      I’ve included it into the post.

      Reply
  2. Ruben Eguiluz

    Great post Nico 🙂
    very well explained the differents ways to create a object in js, I’m looking forward to reading the next one post 😉

    Reply
    1. Nico Cortés

      Thank you for reading it. Next post, coming soon in their browsers. I promise. 🙂

      Reply

Leave a Reply

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