6 secrets of JavaScript Jedis

6 coding tips to take your JavaScript to the next level

JavaScript words

As a front-end developer, I meet a lot of people who write JavaScript. The majority of them do little more than include jQuery and a few plug-ins in order to add a fancy lightbox effect or an image slider. On the opposite end of the spectrum, you have Jedi-level developers who wave their hand over the keyboard and the code basically writes itself.

When you’re between those skill levels, it’s not always clear how to progress. There are many paths to expertise, but if you’re stuck in a rut and could use a push, here are a few concepts that every JavaScript expert should know.

JavaScript secret No. 1: Closures

A closure in JavaScript gives a function access to its parent’s scope. It’s a terribly confusing concept for developers. When I was learning JavaScript, I spent hours debugging code that had unintended closures. After I learned from those mistakes, I thought closures were pretty cool, so I spent hours more trying fruitlessly to use closures to solve my problems.

I eventually learned the deal: Closures become useful when you return inner functions (see higher-order functions below) that still have access to their parent scope. This creates a sort of private or protected environment to keep variables.

// **Closures**

function makeThreeTimer(){

var count = 0;

return function(){

if(count < 3){

console.log(‘doing work’);

count++;

}

else {

throw new Error(‘No more work’);

}

}

}

var threeTimer = makeThreeTimer();

threeTimer(); // logs ‘doing work’ (count gets incremented)

threeTimer(); // logs ‘doing work’ (count gets incremented)

threeTimer(); // logs ‘doing work’ (count gets incremented)

threeTimer(); // throws an error

threeTimer.count; // returns undefined


In the above example, count is accessed and incremented when threeTimer gets invoked and cannot be accessed directly via dot or bracket notation.

JavaScript secret No. 2: Higher-order functions

In functional programming languages, functions are first-class members. They can be passed around like any other value, which opens up interesting possibilities.

Higher-order functions refer to those that consume or produce other functions. Methods on the function prototype, such as call and bind, are both higher-order functions. Techniques such as currying and memoization can both be expressed as higher-order functions. Aspect-oriented programming can also be achieved in JavaScript using higher-order functions.

JavaScript secret No. 3: Invoking functions

After understanding the most common way to invoke a function (using the parentheses operator), it’s time to learn how to use call and apply. The benefit of using call/apply over the parentheses operator is that you can specify the context in which the function will execute (the value of this). You’ll see this often in higher-order functions, particularly when they consume functions to execute later. The internals of the bind method of the Function prototype is a great example of call/apply.

// Possible implementation of bind using apply

function bind(func, context){

return function(){

func.apply(context, Array.prototype.slice.apply(arguments));

}

}

JavaScript secret No. 4: What’s this?

The this keyword is a huge stumbling block for many JavaScript developers to the point that some avoid it altogether. The best description of the topic I’ve seen so far was by Yehuda Katz in his blog post on function invocation. When not using call/apply or bind, the this value will always refer to the global object, except in the following instances:

  1. The function in question was called with the new operator, in which case this points to a new object being constructed.
  2. The function in question is a member of an object, in which case this points to the object.

Rule 2 should be disregarded whenever the function involved is being called asynchronously, such as in a click handler or setTimeout. For example:

Person.getName(); // ‘this’ points to Person

setTimeout(Person.getName, 1000); // ‘this’ points to the global object

JavaScript secret No. 5: Protecting the global scope

One of JavaScript’s flaws is that scripts on a page are all executed in a shared global context. When exploited, this flaw can leave a website vulnerable to cross-site scripting attacks, for example. The shared global context can lead to other problems. For example, many scripts run on a page, and not all of them are always determined by you (such as ads). Those scripts run in the global space and can all access the same global variables. If two of those scripts happen to use the same global variable, they begin interfering with each other. The code then breaks.

Minimizing use of the global scope is a defensive technique that helps eliminate interference and save you hours of debugging time. Chances are you can’t eliminate storing variables globally, but you can minimize your footprint by using techniques like namespacing:

// **Namespacing**
// The global footprint is a single object containing
// all other references needed.

var MyApp = {};

MyApp.id = 42;

MyApp.utils = {

validate: function(){

//do work

}
};

Or the module pattern:

// **Module pattern**
// This relies on immediately invoked anonymous functions and the
// closure they create to maintain access to variables within the
// function.

var MyApp = (function(){

//declare a local variable
var appId = 42;

function getAppId(){

//referring to a variable in this function’s parent scope
return appId;

}

return {
getAppId: getAppId

};
}());

appId; // undefined

MyApp.appId; //undefined

MyApp.getAppId(); // returns 42. 


JavaScript secret No. 6: Inheritance

JavaScript has a long and confusing history with inheritance, for several reasons. Most developers—including many JavaScript developers I’ve met—have a solid understanding of the classical model and are utterly confused by the prototypal model. This makes lots of sense after you peruse a list of languages that use prototypal inheritance.

With the exception of JavaScript, prototypal inheritance is not part of any mainstream language. To make matters worse, it’s possible to emulate the classical model in JavaScript. As a result, there are all sorts of approaches to inheritance, many of them opinionated and contradictory. I suggest avoiding the pseudo-classical approach entirely, as it’s one of JavaScript’s sirens. It looks familiar to most developers, but breaks down quickly because it’s only an approximation.

There are just a few topics every expert JavaScript developer should know, and a high-level overview at that. Are any of these causing you pain? Have I left something out that deserves to be mentioned? Start the conversation in the comments.

This article, “6 secrets of JavaScript Jedis,” was originally published at InfoWorld.com. Keep up on the latest news in application development and read more of Andrew Oliver’s Strategic Developer blog at InfoWorld.com. For the latest business technology news, follow InfoWorld.com on Twitter.

This story, "6 secrets of JavaScript Jedis" was originally published by InfoWorld.

Notice to our Readers
We're now using social media to take your comments and feedback. Learn more about this here.