Old JavaScript tips

Simple Rules

Use {} instead of new Object().
Use [] instead of new Array().
Blocks do not have scope. Only functions have scope.
It is almost always better to use the === and !== operators. The == and != operators do type coercion.
Avoid using eval().
Do not use the Function constructor.
Do not pass strings to setTimeout() or setInterval().

Definitions

Closure
In computer science, a closure is a first-class function with free variables that are bound in the lexical environment. Such a function is said to be "closed over" its free variables. A closure is defined within the scope of its free variables, and the extent of those variables is at least as long as the lifetime of the closure itself. The explicit use of closures is associated with functional programming and with languages such as ML and Lisp. Closures are used to implement continuation passing style, and in this manner, hide state. Constructs such as objects and control structures can thus be implemented with closures.
  • //net.tutsplus.com/tutorials/javascript-ajax/closures-front-to-back/

Booleans (comparison)


'' == '0'          // false
0 == ''            // true
0 == '0'           // true
false == 'false'   // false
false == '0'       // true
false == undefined // false
false == null      // false
null == undefined  // true
true == 1          // true
'' == null         // false
false == ''        // true

Objects

Objects in JavaScript are namespaces. A library or service can be (should be) encapulated in a single object. This can reduce the use of globals down to a single symbol. This can significantly improve modularity (see next item).


NS.myProperty = {
  publicVar: value,
  method: function () {
      ...
  }
};

Modules

//yuiblog.com/blog/2007/06/12/module-pattern/

Modules can be easily constructed out of anonymous JavaScript functions. The advantage of modules is that they allow for private variables and functions which are shared throughout the module. This can result in smaller, faster, and more secure programs than are possible with the object pattern.


NS.myProperty = function () {
  // Module-private variables are defined here
  var myPrivate;

// Module-private functions are defined here function myPrivateFunction () { … }

// Create and return an object containing the public variables and methods. // The methods have priviledged access to the module-private variables and functions. return { publicVar: value, method: function () { … } }; }();

Stacks & Queues

//aymanh.com/9-javascript-tips-you-may-not-know

A stack follows the Last-In First-Out (LIFO) paradigm: an item added last will be removed first. The Array class has 2 methods that provide stack functionality. they are push() and pop(). push() appends an item to the end of the array, and pop() removes and returns the last item in the array. The next code block demonstrates how to utilize each of them:


var stack = [];
stack.push(2);       // stack is now [2]
stack.push(5);       // stack is now [2, 5]
var i = stack.pop(); // stack is now [2]
alert(i);            // displays 5

A queue follows the First-In First-Out (FIFO) paradigm: the first item added will be the first item removed. An array can be turned into a queue by using the push() and shift() methods. push() inserts the passed argument at the end of the array, and shift() removes and returns the first item. let's see how to use them:


var queue = [];
queue.push(2);         // queue is now [2]
queue.push(5);         // queue is now [2, 5]
var i = queue.shift(); // queue is now [5]
alert(i);              // displays 2

It's worth noting that Array also has a function named unshift(). This function adds the passed item to the beginning of an array. So a stack can also be simulated by using unshift()/shift(), and a queue can be simulated by using unshift()/pop().

Note: Array[Array.length] is faster than Array.push(). Testing indicates that using array.length to append to an array is significantly faster than both push() and unshift() in both IE and Mozilla

One-liner to swap two variables


foo = [bar, bar = foo][0];

String Concatenation vs. Array.join

This cannot be stressed enough, doing many string concatenation operations can be a major hit on performance, and it's easy to avoid in many situations. Consider for example that you want to build a string out of many pieces, one bad way to do this is using the + to concatenate all pieces into a huge string, one piece at a time:


str = '';
for (/* each piece */) { str += piece; // bad for performance! } return str;

This method will result in too many intermediate strings and concatenation operations, and will poorly perform overall. A better approach to this problem is using Array.join(), this method joins all array elements into one string:


var tmp = [];
for () {
  tmp.push(piece);
}
str = tmp.join('');
return str;

This method doesn't suffer from the extra string objects, and generally executes faster.

Binding Methods To Objects

Anyone who works with JavaScript events may have come across a situation in which they need to assign an object's method to an event handler. The problem here is that event handlers are called in the context of their HTML element, even if they were originally bound to another object. To overcome this, I use a function that binds a method to an object; it takes an object and method, and returns a function that always calls the method in the context of that object. I found the trick in Prototype, and wrote the following function to use it in projects that don't include Prototype:


function bind(obj, method) {
  return function() {
    return method.apply(obj, arguments);
  }
}

And this snippet shows how to use the function:


var obj = {
  msg: 'Name is',
  buildMessage: function (name) {
    return this.msg + ' ' + name;
  }
}

alert(obj.buildMessage('John')); // displays: Name is John
f = obj.buildMessage; alert(f('Smith')); // displays: undefined Smith g = bind(obj, obj.buildMessage); alert(g('Smith')); // displays: Name is Smith

Sorting With a Custom Comparison Function

Sorting is a common task. JavaScript provides a method for sorting arrays. However, the method sorts in alphabetical order by default. Non-string elements are converted to strings before sorting, which leads to unexpected results when working with numbers:


var list = [5, 10, 2, 1];
list.sort()
// list is now: [1, 10, 2, 5]

The explanation of this behavior is simple: Numbers are converted to strings before sorting them, so 10 becomes '10' and 2 becomes '2'. The JavaScript interpreter compares two strings by comparing the first two characters of each: str1 is considered "less than" str2 if str1's first character comes before str2's first character in the character set. In our case, '1' comes before '2' so '10' is less than '2'.

Fortunately, JavaScript provides a way to override this behavior by letting us supply a comparison function. This function defines how elements are sorted, it takes two compared elements a and b as parameters, and should return:
A value less than zero if a < b.
zero if a == b.
A value greater than zero if a > b.

Programming such a function for number comparison is trivial:


function cmp(a, b) {
  return a - b;
}

Now we can sort our array using this function:


var list = [5, 10, 2, 1];
list.sort(cmp);
// list is now: [1, 2, 5, 10]

This flexibility in Array.sort() allows for more sophisticated sorting. Let's say you have an array of forum posts, each post looks something like:


var post = {
  id: 1,
  author: '...',
  title: '...',
  body: '...'
}

If you want to sort the array by post id's, create the following comparison function:


function postCmp(a, b) {
  return a.id - b.id;
}

It's reasonable to say that sorting using a native browser method is going to be more efficient than implementing a sort function in JavaScript. Of course, data should be sorted server-side if possible, so this shouldn't be used unless absolutely necessary (for example, when you want to offer more than one sort order on one page, and do the sorting in JavaScript).

null, undefined, and delete

JavaScript is difference from other programming languages by having both undefined and null values, which may cause confusion for newcomers. null is a special value that means "no value". null is usually thought of as a special object because typeof null returns 'object'.

On the other hand, undefined means that the variable has not been declared, or has been declared but not given a value yet. Both of the following snippets display 'undefined':


// i is not declared anywhere in code
alert(typeof i);

var i;
alert(typeof i);

Although that null and undefined are two different types, the == (equality) operator considers them equal, but the === (identity) operator doesn't.

JavaScript also has a delete operator that "undefines" an object a property (thanks zproxy), it can be handy in certain situations, you can apply it to object properties and array members, variables declared with var cannot be deleted, but implicitly declared variables can be:


var obj = {
  val: 'Some string'
}

alert(obj.val); // displays 'Some string'

delete obj.val; alert(obj.val); // displays 'undefined'

parseInt() scoffs at your base ten numbering system

Guess what the value of monthInt (below) will be:


month = "09";

var monthInt = parseInt(month)

If you guessed 9, then gotcha! The answer is 0.

When the string begins with a zero, parseInt interprets the value in base 8. To fix this problem, do the following:


var monthInt = parseInt(month , 10);

Now monthInt will be equal to 9. The second argument forces parseInt to use a base ten numbering system.

References