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-knowA 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];
- //twitter.com/izs/status/17744109574
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.
- //aymanh.com/9-javascript-tips-you-may-not-know
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
- //aymanh.com/9-javascript-tips-you-may-not-know
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'
- //aymanh.com/9-javascript-tips-you-may-not-know
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.
- //www.fitzblog.com/tabid/17782/bid/2127/Nine-Javascript-Gotchas.aspx
References
- //aymanh.com/9-javascript-tips-you-may-not-know
- //www.crockford.com/javascript/private.html
- //icant.co.uk/sandbox/bonsaimenu/index.html
- //phrogz.net/JS/Classes/OOPinJS.html
- //yuiblog.com/blog/2007/06/12/module-pattern/
- //www.fitzblog.com/tabid/17782/bid/2127/Nine-Javascript-Gotchas.aspx
- //ejohn.org/blog/untold-javascript-secrets/
- //ejohn.org/blog/how-javascript-timers-work/
- //net.tutsplus.com/tutorials/javascript-ajax/closures-front-to-back/
- //en.wikipedia.org/wiki/Closure_(computer_science)
- //dev.opera.com/articles/view/javascript-best-practices/
- //www.smashingmagazine.com/2010/04/20/seven-javascript-things-i-wish-i-knew-much-earlier-in-my-career/
- //www.asp.net/ajaxlibrary/act_contribute_codingStandards_Design.ashx
- //twitter.com/izs/status/17744109574