Fresh Blurbs

Object Oriented JavaScript from Classical OO Perspective

For programmers accustomed to conventional Object-Oriented languages, such as: Java or C++, JavaScript's Object-Oriented implementation can often be confusing. Contrary to the popular misconception, this is not due to JavaScript's "flawed object-orientedness", but it is so because JavaScript is a functional language and its approach to object-orientedness is simply different. Not flawed—just different.

Let's elaborate on that.

JavaScript is a class-free object-oriented language. It uses prototypal inheritance rather than class-based one. To properly understand how it works, we need to break away from the accustomed thinkning patterns, formed by usage of languages like Java, Ruby or C++.

Rule #1: functions in Javascript are objects, and there are no classes! To fully understand prototypal inheritance, we need to accept this as a fact and refuse the temptation of creating faux notions of a class in Javascript. JavaScript is a functional language, and functions are first-class citizens:

  • Functions are objects, they are always instantiated and assigned to variables
    • function name() {} is just a shortcut syntax to var name = function() {}
  • Since they are objects, functions can be passed as arguments to other functions
  • Functions have structure: properties (variables) that can point to other functions, objects or primitive types.
  • Functions have prototypes and can share features of other functions using prototypal inheritance.

But How Do You Do OO Without a Class?

The notion of a Class in conventional OO languages, provides two main features: type-checking and code re-use. Given that JavaScript is a dynamically-typed language, there's little to no benefit using classes for typing. As for code re-use: due to increased flexibility, prototypal inheritance can actually lead to more code re-use than class-based inheritance. So no problem there, as well.

One last time: if you want to understand JavaScript's OO and get productive in it, you should not try to fall in a trap of figuring out "what is a class in JavaScript"? There is no Class. By design. Make peace with it and enjoy.

Getting used to prototypal inheritance takes time and experience. Books like Douglas Crockford's JavaScript; The Good Parts can be helpful, but if you are just starting out it also helps to have examples of how you'd do things in Javascript which you'd normally be using classes for.

TL;DR: Survival Guide Only

How do we create a 'parent' function (note: not 'a class') in Javascript and assign an inheritable function prototypally to it? This is analogous to assigning a method to a class, in conventional languages. Furthermore, how do we define a 'child' function, tell it to prototypally get features from the 'parent' and re-use parent's constructor? This would be analogous of 'parent class constructor inheritance' in the class-based object-oriented languages.

Following code snippet does all of that without using any third-party libraries:

// Parent definition
function Animal(name) {
  if (!name) return;
  this.name = name;  
}

// Defining a member function on the parent
Animal.prototype.getName = function() {
  return this.name;
}

// Function definition with constructor "inheritance"
function Cat(name) {   
  Animal.call(this,name); // "inherit" constructor 
  this.constructor = Cat; // "fix" constructor pointer. Read further for details.
};

// Telling "child" to "extend" the "parent". This is sugar syntax.
Cat.prototype = new Animal;

// Or, for server-side, V8 code, the preferred method is to use
// __proto__ because it does not "damage" Cat's constructor pointer and does
// not require the "fix" which we had to apply in the code above. Here's how 
// you'd do it:
// Cat.prototype.__proto__ = Animal.prototype;

// Testing the whole thing
var kitty = new Cat("Smokey");
console.log(kitty.getName());

// Note the difference between the two when using __proto__ vs. not using it:
// console.dir(Cat);
// console.dir(Cat.prototype.constructor);

A bunch of people try to think of "prototype" as being analogous to the notion of a "class". This is wrong, because the whole point of a class is that you can instantiate it. You are not instantiating a "prototype" in Javascript, you are instantiating functions.

I think the best way to think of a "prototype" is to look at it like a public/private marker. Functions that are defined through a prototype are "public" for sharing the functionality (call it "inheritance" if you will), whereas the functions that you just attach to a function are instance-specific and "private" in regards with sharing/inheriting.

There are also a handful of libraries that create "sugar" syntaxes and make prototypal inheritance look more like "class"-based inheritance.

I believe attempts to create a notion of a "class" in Javascript are misguided. There is no need to be stubborn about class-based inheritance and reject prototype-based inheritance in JavaScript, just because we may be used to class-based inheritance in other languages. It's much better to embrace full functional flexibility of what JavaScript provides out of the box.

There is no such thing as a "class" in Javascript. It is so by design.

comments powered by Disqus