THE KEY TO JAVASCRIPT

muyiwa akin-ogundeji
13 min readJan 21, 2016

--

Javascript (JS)is an amazing language, it’s history is full of drama from creation through being scorned as a ‘toy language’ and now becoming a mainstream language ‘recognized’ as suitable for creating performant, scalable web applications.

Despite the increasing popularity of JS it still is a ‘misunderstood’ language (as Douglas Crockford said). A major reason for being misunderstood and improperly applied is that many users of JS lack the key which unlocks the full potential of this amazing and dare i say — revolutionary — programming language.

You see, many people who use JS ‘speak’ JS with an ‘accent’ (i got that from Eric Elliot), this means that either because of their background in other programming languages (C, C++, Java etc) or because of how they learnt JS, they approach JS with a ‘bias’ which clouds how they perceive and apply JS in their projects. A really good example of this ‘accent’ is trying to implement ‘inheritance’ using ‘classes’ (read ‘constructor function calls’) rather than implementing inheritance though ‘objects’ (read ‘the prototype chain’).

In this article we will come to understand the ‘key’ to JS and discover how this ‘key’ unlocks for us the full power of this amazingly powerful and expressive programming language, we will come to understand that JS confers us i.e. developers with the power to express our ideas as we see fit without the constraints of many traditional programming languages, we will also come to understand that JS is not flawed in any way but is simply what it is — a language developed to address a problem but which is flexible enough to be applied to other problem domains.

Of course this doesn’t mean JS is perfect — no humanly devised solution is, but JS is just right for what it needs to be used for and we will come to appreciate this through the course of this article. This is why statements such as “Atwood’s Law” have been coined.

THE KEY IS NOT A SINGLE THING

The first thing we need to understand is that the ‘key’ to JS is not a single ‘thing’ — rather it’s an ‘alloy’, an ‘amalgam’ a ‘gestalt’ (if you prefer) composed of parts which beautifully combine to form a whole which is greater than the sum of the parts.

The ‘key’ to JS is composed of 1) Objects 2) Functions and 3) Asynchronity. These 3 elements combine to unlock the full power of JS. Let’s begin to understand the ‘key’.

OBJECTS

A JS Object is a collection of ‘properties’, each property is a ‘mapping’ between a ‘key’ and a ‘value’. A ‘value’ can be any valid JS ‘value type’ — this is why what we call ‘methods’ in JS are more accurately called ‘properties’ since they’re simply properties whose value is a function!

Ok, so we get that JS Objects are collections of ‘properties’ is that all? No! Because they’re ‘first class types’ JS Objects can be passed around any JS code, thus JS Objects are a very clean way to encapsulate ‘state’. This makes them very important in developing maintainable code. Since the JS Object is a value, it means we can mutate the ‘state’ we’re interested in by simply modifying the appropriate ‘property’ of the object that represents that ‘state’. This means that a function can have all the ‘state’ it needs to effect some change represented in totality by the appropriate object. This is a key insight into understanding how JS Objects can be used to represent interfaces between the user and the application (i.e. UIs) and also between different applications (i.e. APIs).

Furthermore, unlike the vast majority of ‘Object Oriented’ programming languages, JS makes it really easy and straightforward to work with ‘Objects’ as representations of either ‘real world’ entities/constructs or ‘abstract’ entities/constructs. In JS, an Object can be created and manipulated without needing a ‘blueprint’ i.e. ‘class’ to define it’s behavior!

Do we need to work with a ‘car’ object? Simply create one as follows:

var car = {
make: 'Ford',
type: 'salon',
engine_capacity: 'V8',
start: function () {
return console.log('Engine started!');
},
accelerate: function () {
return console.log('Going faster!');
},
brake: function () {
return console.log('Slowing down!');
}
};

Just like that we’ve created a ‘car’ object. And if we need more cars — we simply create them. This makes JS very useful as it removes a layer of abstraction i.e. the ‘class’ and allows us to reason more starightforwardly about our code.

So why is the use of ‘class’ so popular? I suggest 2 reasons.

  1. ‘Typecasting’: In traditional OO languages, an object can’t simply ‘be’ an object — it has to be an ‘instance’ of a ‘class’, so you’d have ‘people’ objects and ‘car’ objects and so forth. Because the ‘class’ created the object you could identify what an ‘object’ is by checking it’s type. Something like:
//this is imaginary
var car = instance of Car class;
typeof car;//Car

But in JS, objects can simply ‘be’ objects and so we would have the following:

var car = {
make: 'Ford',
------------
};
typeof car; 'object'

For many people from the traditional OO world, this is very unpleasant! A ‘car’ should be a ‘Car’ object and not simply an ‘object’! But this isn’t so in JS — in JS we don’t have ‘types’ of objects, we simply have objects. This is a key insight to allow us to use JS effectively.

I could go on and on but allow me to refer you to a most valuable resource by Kyle Simpson. This book will provide key insight into the true nature of objects in JS.

2. ‘Inheritance, Polymorphism, Encapsulation’: These are treasured patterns in the world of OO and they are valid solutions to the problems they were created to address, however in JS, things don’t work the same way as it does in traditional OO. In traditional OO, in order to create multiple ‘car’ objects, we create multiple ‘instances’ of the ‘Car’ class. This is done so that the default ‘behavior’ of the ‘car’ object conforms to a pattern defined on the ‘Car’ class but is still modifiable on any ‘car’ object if we so choose (this is essentially what ‘inheritance’ is all about — a mechanism which allows objects to access functionality (properties/methods) not defined on themselves). In JS because we can directly create and manipulate Objects, a different mechanism for implementing inheritance was adopted and that is the ‘infamous’ prototypical inheritance.

What this means in essence is that every object in JS is linked to some other object (even ‘null’) called it’s ‘prototype’and it ‘inherits’ some default behavior from that object. For instance:

var obj = {};
obj.toString();//"[object Object]"

Hold up! How come ‘obj’ didn’t throw an error when an undefined method ‘toString()’ was called on it? This is the power of prototypical inheritance!

What if we want to create multiple ‘car’ objects or even multiple ‘Ford’ cars which differ only in some details — maybe color, engine type etc? Surely the ‘only way’ that is possible is by defining a ‘class’ and the creating instances right? In traditional OO, that would be so, but in JS we chuckle with glee! Behold:

var fordProtoype = {
start: function () {
return console.log('Engine started!');
},
accelerate: function () {
return console.log('Going faster!');
},
brake: function () {
return console.log('Slowing down!');
}
};
function fordFactory(configObj) {
var newFord = Object.create(fordPrototype);
newFord.color = configObj.color;
newFord.model_name = configObj.model_name;
newFord.topSpeed = configObj.topSpeed;
return newFord;
}
var fordEscort = fordFactory({
color: 'black',
model_name: 'Escort',
topSpeed: '240 km/h'
});
fordEscort.start();//'Engine started!'

The preceding code snippet shows how ‘easy’ it is to implement ‘inheritance’ in JS without needing to ‘accent’ our JS with overtones from traditional OO which merely ‘deceive’ us into thinking we know what we’re doing and what’s going on when the reality is that JS is doing something totally different under the hood. Likewise other concepts such as ‘encapsulation of private data etc’ and ‘polymorphism’ are implementable in JS using the proper JS constructs without needing to ‘coerce’ JS into appearing to behave in a way which it is totally alien to it’s nature.

Having said that, is it possible to implement ‘classes’ in JS to achieve some functionality or the other? Yes it is, by using functions and making ‘constructor’ calls i.e. calling the function with the ‘new’ keyword, we can implement classes (or simply using ES6 ‘class’ keyword) but it’s important to understand what’s happening under the hood and realize that we’re not truly creating blueprints for object instances but merely creating prototypical linkages between one object type (i.e. the ‘instance’) and another (i.e. the ‘class’ because in JS, Functions are objects!).

Again i refer you the excellent book by Kyle Simpson, he does a far better job than i in making the nature of JS objects very clear.

The fact is that the flexible nature of JS combined with the power of JS Objects allows us to really screw ourselves up when we don’t have a clear understanding about the nature of objects in JS. Objects are an important element which makes up the ‘key’ to JS and a clear understanding of what they are and how they function is essential if we are to truly master JS.

FUNCTIONS

Functions! Some believe that functions are the ‘key’ to JS, this is because in JS Functions are so central to implementing any non-trivial operation that it’s unimaginable to think something else could be just as important.

As we’ve seen already, Objects are also really important in unleashing the full power of JS. One is not more important than the other, they play complementary roles in making JS such a powerful language.

The first thing to understand about JS functions is that in JS, functions are actually a special variant of the ‘Object’ type! This is a reason why JS functions are ‘first class citizens’ and can be passed around JS code just like any other JS ‘value type’.

First class functions makes it possible to implement a functional programming style in JS when necessary — that ability is so important as it allows JS to be used in a powerfully expressive yet declarative manner when necessary. For instance, compare the following code snippet:

//procedural imperative implementation 1
var arr = [1,2,3,4,5,6,7,8,9], i, len = arr.length;
for (i = 0; i < len; i++) {
console.log(arr[i]);
}
//declarative implementation 2
var arr = [1,2,3,4,5,6,7,8,9];
arr.forEach(function (el){
console.log(el);
});

The difference in the 2 code samples is clear, the first is what obtains in traditional OO languages and the 2nd is what obtains in traditional Functional Programming languages — both are possible with JS!

Functions in JS are used to do 2 things 1) provide a ‘relationship’ between input ‘data’ and output ‘result’ — this is particularly so when we do not want ‘side effects’ in our code or we require that the logic represented by the function simply ‘compute’ the result of some operation on a given piece of data. 2) mutate ‘state’ by ‘doing’ something e.g. if we wanted the function to respond to user input and perform some action which provides feedback to the user by changing the application in some way.

There are different ways through which JS functions can be ‘ created’ e.g. function declaration or function expression, JS functions can also be anonymous or named. Because JS functions are values, they can be passed to other functions as arguments this is why JS is such a natural fit for ‘event driven’ programming!

JS functions are the key to creating web applications which are responsive to user actions, they’re the ‘secret’ to building non-blocking, asynchronous applications and they make it ‘easy’ to implement some patterns in JS which are more difficult in other OO languages.

Because JS functions are objects, they require a reference to the ‘context’ within which they are executed. This reference is provided by the ‘this’ variable which points to the ‘calling/owning’ context of the JS function within which the ‘state’ of the JS function has meaning.

In other words, ‘this’ is what allows the variables which a JS function uses to perform it’s operation to have ‘meaning’ i.e. to have a direct reference in the memory space allocated to the JS function. Kyle’s book explains ‘this’ in greater detail and a previous article which i wrote also provides background on ‘this’.

Because of the preceding concept and the fact that JS functions are also values — the ‘closure’ mechanism can be used to retain the ‘state’ of a JS function in a similar manner to how a JS object can be used to encapsulate ‘state’. This is why Anton came to understand that closures and objects achieve the same goal — they encapsulate state!

These insights into JS functions provide the merest introduction to the reason they are such an important component of the ‘key’ to JS. It’s impossible to master JS without mastering JS functions, it’s impossible to use the full power of JS if the full power of JS functions is neglected.

ASYNCHRONITY

In the world of ‘event driven’ programming — JS is king! The reason is because JS functions, objects and the single threaded nature of JS (plus other ‘stuff’ like the event loop, run to completion etc) make it much easier in JS to implement async programs than in almost any other programming language.

When a user hovers over an element with a mouse, JS’s async capabilities are what allow it to execute the proper function in response to this ‘event’ and provide the appropriate response by the application.

There are 3 ‘mechanisms’ in JS which make it possible to effectively handle async: 1) Single Threaded nature 2) Run to Completion 3) Events and the Event loop.

Single Threaded Nature: JS is single threaded by nature, this means that there’s only one JS thread per browser window/tab. When this is coupled with JS ‘interpretation’ of code i.e.e line by line execution, it means that any code block currently running will have each statement executed line by line. By itself, this doesn’t tell us much but when combined with the next point things begin to become clearer.

Run to Completion: This attribute of JS ensures that any piece of code currently under execution cannot in anyway be interrupted before it returns. When combined with the Single threaded nature of JS it implies that if a callback is invoked asynchronously from within a currently executing statement, that callback cannot later interrupt the executing code if it returns before the code that called it completes.

Take a moment to review what i just said — it’s really powerful stuff! It gets better and becomes clearer when we examine the 3rd piece of the ‘puzzle’ — Events and the Event Loop.

Events and the Event Loop: What makes a function async? It’s not what you think i.e. merely accepting a callback as an argument doesn’t make a function async, consider the following:

function foo(val, cb) {
debugger;
cb(val);
}
function bar(val) {
return val * val;
}
foo(10, bar);//100

In the preceding code snippet, it may appear that ‘foo’ is asynchronously calling ‘bar’ i.e. ‘foo’ returns before ‘bar’ is called, but if you examine the call stack, you’ll see that what actually happens is that ‘bar’ is synchronously called from within ‘foo’ and ‘bar’ returns before ‘foo’!

Consider another code snippet:

function foo(val, cb) {
return setTimeout(function () {
return cb(val);
}, 1000);
}
function bar(val) {
return console.log(val * val);
}
foo(10, bar);//returns timer id
//at least one second later
100

To clearly understand the difference between the 2 code snippets you need to examine the debugger — you’ll notice that for the 2nd snippet — ‘foo’ actually returns and then at least 1 second later ‘bar’ returns!

So what’s going on? It’s the power of the 3rd piece of the JS asynchronity puzzle — events and the event loop.

In JS, a function can only be called async when it’s invoked in response to some event which takes place at some undetermined time in the future. Lets step back for a minute- we know that JS is single threaded and has a run to completion operation and we understand what that means, now we need to understand the place of events and the event loop.

In JS runtime environments, ‘events’ happen all the time. Almost every single action that takes place in the JS environment fires an event, these events can be ‘listened for’ by our code and we can cause JS to invoke the appropriate piece of code when the event occurs. When events are fired they are placed in a queue, this queue is visited by the JS runtime host e.g. a browser whenever the currently executing JS thread ends.

SO what happens is we invoke some code, it runs to completion, perhaps during the time it was running some actions took place on the UI, data was received over the network etc these other I/O operations will be ‘noted’ because when they occur they fire events which are placed on the queue — but while the currently running code is executing, these events will not be responded to (which is why its a bad idea to make long running code execute synchronously — it causes the browser to ‘freeze’) until the presently executing code (current thread) has completed and JS has returned control to the host environment.

When the host gets control from JS, it examines the queue and informs JS of the next event that’s available — if some code has been assigned to handle this event, then JS invokes the function and causes it to run to completion before returning control to the host. It’s this continuous placing of events on the queue and checking the queue by the host (after control has been returned by JS) that is called the event loop.

Implicitly or explicitly, a function has to be assigned to an event in order to be invoked when the event occurs. Consider the foo function which used the timer, by design, implicitly and internally, JS assigns the callback passed to the timer to be invoked after the provided duration (1000 ms) has elapsed. This is why after the elapsed time JS ‘knows’ the proper function to call.

These 3 mechanisms make JS absolutely great for developing event driven applications which implement a non blocking I/O structure. An in our modern world of big data — which application can afford to neglect this capability? None! That’s why almost all the giants of big data — Facebook, Google, Twitter, Paypal etc have developed JS frameworks or libraries to take advantage of the power of JS in handling async!

These 3 elements — JS Objects, Functions and Asynchronity are truly the ‘key’ to unlocking the full power of JS and setting us firmly on the road to mastery.

I’d have liked to really dig deep into these 3 subjects but i’m sure you can get better background on them from more qualified sources than me.

Thank you for reading, please leave comments below or reach out to me on twitter.

--

--