JavaScript is object oriented

And no: I’m not talking about classes

BrenDt
Just JavaScript

--

A few days ago, I made a tweet stating JavaScript is object oriented and that I wasn’t talking about classes. It got a lot more response than expected. My opinion is of course based on the work of Kyle Simpson’s You don’t know JS, so I won’t be telling anything new here. My goal today is mainly to intrigue you, and widen you view about JavaScript.

Object oriented: using a methodology which enables a system to be modelled as a set of objects which can be controlled and manipulated in a modular manner.

Object oriented programming is everywhere. As the definition states: it enables for a modular design and reusable code. Many languages use the class pattern for this. By doing so, you’ve got classes, inheritance, polymorphism, etc. I say class pattern because classes are not a requirement for object oriented programming. It’s a common style of OOP and many languages only provide this class based paradigm as a way to work with objects. It’s not the only way though. The main thought behind object oriented programming is, well, objects.

Developers experienced in other languages are often confused by JavaScript because of classes. You might have read about OO JavaScript and found out you could create a function (huh?) which can be used as a constructor (what?), and you could also inherit other functions. Well, actually their prototypes (uuh?). But you would need to hard-copy some stuff over (why?). And some things should be in the function, others in its prototype (wat?). Now you’re stuck with either some crappy code, or a dependency on one of too many frameworks. Still, it doesn’t feel right. Many give up here.

So take a step back and rethink why you really wanted to use classes. They might be convenient and easy to understand but that’s biased. If you were to explain class oriented programming to a layman, you’d need a lot of time (as we all needed). The reason we tend to use classes is because we’re used to it. We learned it. The same way we can learn not to write class oriented code.

A world of objects

Hacking class-like behaviour in JavaScript might be possible, but shouldn’t be done. There are many reasons why, and you can definitely learn about them in Kyle’s books. JavaScript was made to work with objects, and that’s it. So let’s take a look at how this works, it’s actually surprisingly easy.

var Foo = {
init(id) {
this.type = 'foo';
this.setId(id);
},

setId(id) { this.id = id; },
getId() { return this.id; },
};
var baz = Object.create(Foo);
baz.init(10);

You’ll probably notice a few things here.

  • The use of Object.create() instead of the new keyword. This might look awkward at the start. Remember we’re unlearning class oriented programming, so things will be different.
  • Another thing to notice is the init() function which we have to call. It might look just like another line of code, but we’ll get into that soon.

So what does Object.create() actually do? As you saw, we made a plain old JavaScript object called Foo and added some properties to it. Note that I’m using ES2015 syntax here. Older versions of JavaScript required named properties like so.

var Foo = {
init : function(id) { /* ..*/ },
setId : function (id) { /* ..*/ },
getId : function () { /* ..*/ },
}

Because we’re in an object, we have to add a comma after each entry. That’s basic JavaScript syntax. Calling Object.create() tells JavaScript to create a new object, based on the given prototype. This prototype cannot take any construction arguments, hence the optional init() function. When you don’t need extra initialisation, this function call is not required.

Inheritance and polymorphism

It’s good to keep in mind that we’re not per se trying to mimic class-like behaviour. But also with objects, some kind of inheritance will be useful. The way we do this is easy.

var Bar = Object.create(Foo);Bar.init = function(id, name) {
this.type = 'bar';
this.id = id;
this.name = name;
}
Bar.setName = function(name) {
this.name = name;
};
Bar.getName = function() {
return this.name;
}
var baz = Object.create(Bar);
baz.init(10, 'test');

If we were to log the contents of baz, we’d see this.

{
"type" : "bar",
"id" : 10,
"name" : "test"
}

This is exactly what we expected.What happened here? We created a new object called Bar, based on the Foo object from the previous example (inheritance). We added functions to get and set an extra value “name”. Finally we overrode the init() function to take an extra argument (polymorphism). Simple enough? You can chain these objects infinitely because, well, they’re just objects.

Immutable values

You might want some immutable values on an object. Values you can read, but not change or delete. We can use Object.defineProperty() to do that. What this function does, is adding a property to an object with some extra options.

Object.defineProperty(Foo, ‘type’, {
value : ‘FOO’,
writeable : false,
configurable : false,
enumerable : true,
});

We’ve set four descriptor keys:

  • value, which is the value of the property.
  • writeable, to disable the property to get a new value.
  • configurable, to disable the same property being added (and overridden) again with Object.defineProperty().
  • enumerable, to be able to iterate over this property. The property will show up inObject.keys(), and be parseable with JSON.stringify().

This results in following behaviour:

Foo.type = ‘BAR’; // TypeError// TypeError
Object.defineProperty(Foo, ‘type’, {
value : ‘BAR’,
writeable : false,
configurable : false,
enumerable : true,
});
// console.log(FOO)
{
“type” : “FOO”
}
var baz = Object.create(Foo);
baz.type = 'BAR'; // TypeError
console.log(baz.type); // "FOO"

Be sure to check out the API reference for Object.defineProperty(). This function has a few more options which can be set.

Static functions

In class oriented programming, static functions and variables are set on the class itself. This allows you to work without an instance of the class. Because we don’t have classes, you might think we don’t have static functions. Let’s think about how ridiculous this thought actually is.

  • Static functions are a way to not instantiate an object when using class-global behaviour.
  • In class oriented programming, this is some kind of workaround. You cannot have functionality without an object, classes are just blueprints.

So here we have an example of why objects are the more sane way to see static functionality.

var Foo = {
addition : 5,
add(param) {
return param + this.addition;
},
init(id) {
this.setId(id);
},
};
console.log(Foo.add(3)); // 5
var baz = Object.create(Foo);

We’re just using Foo’s functionality on the Foo object. Later we can create a new object baz which also has all this functionality.

Abstract and interfaces

In class oriented programming, abstract classes are classes which can’t be instantiated. Interfaces are a subset of abstract classes, with no function implementation or variables, just function definitions. This functionality isn’t possible because, like said before, we’re not working with classes.

Copies and references

There’s an important detail about how Object.create() creates new objects. The prototype of one object is copied to an new one. That means the original Foo object will never be modified when we use it. When needed, we can create a new object from Foo with modified behaviour. This object can be used as another prototype to create other objects, like we did with Bar.

This copy mechanism implies that there is no concept of parent objects. An object has all the functionality in itself and never a parent reference. This, again, is another way of thinking, but by no means a constraint.

ES2015 class

As you probably know, ES2015 adds syntax for classes. It’s important to understand that JavaScript classes are built upon the same concepts. There’s is more complexity to it than just this blogpost though.

Furthermore, think about class frameworks using the hacked way to create “classes”. Functions are a subset of Object in JavaScript. These frameworks are built upon the same ideas.

I shared some techniques with you on how to work with objects. To compare things one-to-one with classes wouldn’t be fair. After all, it are two different ways of programming. I find that working with plain objects has a lot of benefits in JavaScript. Thats because the language was designed to work with objects.

It’s your personal preference but I hope this post widened your view about OO in JavaScript. Don’t forget to read this and object prototypes from the You don’t know JS series when you’ve got the time. There’s a lot more in-depth information for you there. Thanks for reading, and don’t forget to leave a recommend below. Feel free to send me a tweet if you want to discuss the topics of this post more, or just leave a reply here.

Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. — Martin Golding

My name is Brent, I read, learn and think a lot about JavaScript. Sometimes I even write some thoughts down. If you’ve found this article useful, feel free to hit the recommend button below and leave a reply. You can also follow me on Twitter if you’d like.

--

--