6 secrets of JavaScript Jedis - DOTNET

6 secrets of JavaScript Jedis

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. (Brought to you by closures)
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 [4].
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.
Copyright © 2015 DOTNET All Right Reserved