312
votes

What "Hidden Features" of JavaScript do you think every programmer should know?

After having seen the excellent quality of the answers to the following questions I thought it was time to ask it for JavaScript.

Even though JavaScript is arguably the most important Client Side language right now (just ask Google) it's surprising how little most web developers appreciate how powerful it really is.

30
Didn't you mean "Having seen the rep. points and views this other question attracted, I thought I'd ask almost exactly the same question to boost my own"? ;-)Bobby Jack
Sure, pessimist. :) I'd considered making this a community question. Also, after you get a certain number of points it's all diminishing returns.Allain Lalonde
Fair enough - it doesn't look as if you 'need' the rep! I guess I just have a big issue with the C# one - doesn't exactly seem to me like the type of question for which this site was intended.Bobby Jack
Yeah, maybe not, but I found the knowledge in the answers great. I think you'd be hard pressed to expose an average C# programmer to all of it in one place if not for SO. It'd take years of playing with it to come up with the same hard won list.Allain Lalonde
I've been writing JavaScript professionally for 10 years now and I learned a thing or three from this thread. Thanks, Alan!Andrew Hedges

30 Answers

373
votes

You don't need to define any parameters for a function. You can just use the function's arguments array-like object.

function sum() {
    var retval = 0;
    for (var i = 0, len = arguments.length; i < len; ++i) {
        retval += arguments[i];
    }
    return retval;
}

sum(1, 2, 3) // returns 6
204
votes

I could quote most of Douglas Crockford's excellent book JavaScript: The Good Parts.

But I'll take just one for you, always use === and !== instead of == and !=

alert('' == '0'); //false
alert(0 == ''); // true
alert(0 =='0'); // true

== is not transitive. If you use === it would give false for all of these statements as expected.

189
votes

Functions are first class citizens in JavaScript:

var passFunAndApply = function (fn,x,y,z) { return fn(x,y,z); };

var sum = function(x,y,z) {
  return x+y+z;
};

alert( passFunAndApply(sum,3,4,5) ); // 12

Functional programming techniques can be used to write elegant javascript.

Particularly, functions can be passed as parameters, e.g. Array.filter() accepts a callback:

[1, 2, -1].filter(function(element, index, array) { return element > 0 });
// -> [1,2]

You can also declare a "private" function that only exists within the scope of a specific function:

function PrintName() {
    var privateFunction = function() { return "Steve"; };
    return privateFunction();
}
162
votes

You can use the in operator to check if a key exists in an object:

var x = 1;
var y = 3;
var list = {0:0, 1:0, 2:0};
x in list; //true
y in list; //false
1 in list; //true
y in {3:0, 4:0, 5:0}; //true

If you find the object literals too ugly you can combine it with the parameterless function tip:

function list()
 { var x = {};
   for(var i=0; i < arguments.length; ++i) x[arguments[i]] = 0;
   return x
 }

 5 in list(1,2,3,4,5) //true
153
votes

Assigning default values to variables

You can use the logical or operator || in an assignment expression to provide a default value:

var a = b || c;

The a variable will get the value of c only if b is falsy (if is null, false, undefined, 0, empty string, or NaN), otherwise a will get the value of b.

This is often useful in functions, when you want to give a default value to an argument in case isn't supplied:

function example(arg1) {
  arg1 || (arg1 = 'default value');
}

Example IE fallback in event handlers:

function onClick(e) {
    e || (e = window.event);
}

The following language features have been with us for a long time, all JavaScript implementations support them, but they weren't part of the specification until ECMAScript 5th Edition:

The debugger statement

Described in: § 12.15 The debugger statement

This statement allows you to put breakpoints programmatically in your code just by:

// ...
debugger;
// ...

If a debugger is present or active, it will cause it to break immediately, right on that line.

Otherwise, if the debugger is not present or active this statement has no observable effect.

Multiline String literals

Described in: § 7.8.4 String Literals

var str = "This is a \
really, really \
long line!";

You have to be careful because the character next to the \ must be a line terminator, if you have a space after the \ for example, the code will look exactly the same, but it will raise a SyntaxError.

145
votes

JavaScript does not have block scope (but it has closure so let's call it even?).

var x = 1;
{
   var x = 2;
}
alert(x); // outputs 2
144
votes

You can access object properties with [] instead of .

This allows you look up a property matching a variable.

obj = {a:"test"};
var propname = "a";
var b = obj[propname];  // "test"

You can also use this to get/set object properties whose name is not a legal identifier.

obj["class"] = "test";  // class is a reserved word; obj.class would be illegal.
obj["two words"] = "test2"; // using dot operator not possible with the space.

Some people don't know this and end up using eval() like this, which is a really bad idea:

var propname = "a";
var a = eval("obj." + propname);

This is harder to read, harder to find errors in (can't use jslint), slower to execute, and can lead to XSS exploits.

144
votes

If you're Googling for a decent JavaScript reference on a given topic, include the "mdc" keyword in your query and your first results will be from the Mozilla Developer Center. I don't carry any offline references or books with me. I always use the "mdc" keyword trick to directly get to what I'm looking for. For example:

Google: javascript array sort mdc
(in most cases you may omit "javascript")

Update: Mozilla Developer Center has been renamed to Mozilla Developer Network. The "mdc" keyword trick still works, but soon enough we may have to start using "mdn" instead.

143
votes

Maybe a little obvious to some...

Install Firebug and use console.log("hello"). So much better than using random alert();'s which I remember doing a lot a few years ago.

120
votes

Private Methods

An object can have private methods.

function Person(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;

    // A private method only visible from within this constructor
    function calcFullName() {
       return firstName + " " + lastName;    
    }

    // A public method available to everyone
    this.sayHello = function () {
        alert(calcFullName());
    }
}

//Usage:
var person1 = new Person("Bob", "Loblaw");
person1.sayHello();

// This fails since the method is not visible from this scope
alert(person1.calcFullName());
99
votes

Also mentioned in Crockford's "Javascript: The Good Parts":

parseInt() is dangerous. If you pass it a string without informing it of the proper base it may return unexpected numbers. For example parseInt('010') returns 8, not 10. Passing a base to parseInt makes it work correctly:

parseInt('010') // returns 8! (in FF3)
parseInt('010', 10); // returns 10 because we've informed it which base to work with.
97
votes

Functions are objects and therefore can have properties.

fn = function(x) {
   // ...
}

fn.foo = 1;

fn.next = function(y) {
  //
}
91
votes

I'd have to say self-executing functions.

(function() { alert("hi there");})();

Because Javascript doesn't have block scope, you can use a self-executing function if you want to define local variables:

(function() {
  var myvar = 2;
  alert(myvar);
})();

Here, myvar is does not interfere with or pollute the global scope, and disappears when the function terminates.

83
votes

Know how many parameters are expected by a function

function add_nums(num1, num2, num3 ){
    return num1 + num2 + num3;
}
add_nums.length // 3 is the number of parameters expected.

Know how many parameters are received by the function

function add_many_nums(){
    return arguments.length;
}    
add_many_nums(2,1,122,12,21,89); //returns 6
79
votes

Here are some interesting things:

  • Comparing NaN with anything (even NaN) is always false, that includes ==, < and >.
  • NaN Stands for Not a Number but if you ask for the type it actually returns a number.
  • Array.sort can take a comparator function and is called by a quicksort-like driver (depends on implementation).
  • Regular expression "constants" can maintain state, like the last thing they matched.
  • Some versions of JavaScript allow you to access $0, $1, $2 members on a regex.
  • null is unlike anything else. It is neither an object, a boolean, a number, a string, nor undefined. It's a bit like an "alternate" undefined. (Note: typeof null == "object")
  • In the outermost context, this yields the otherwise unnameable [Global] object.
  • Declaring a variable with var, instead of just relying on automatic declaration of the variable gives the runtime a real chance of optimizing access to that variable
  • The with construct will destroy such optimzations
  • Variable names can contain Unicode characters.
  • JavaScript regular expressions are not actually regular. They are based on Perl's regexs, and it is possible to construct expressions with lookaheads that take a very, very long time to evaluate.
  • Blocks can be labeled and used as the targets of break. Loops can be labeled and used as the target of continue.
  • Arrays are not sparse. Setting the 1000th element of an otherwise empty array should fill it with undefined. (depends on implementation)
  • if (new Boolean(false)) {...} will execute the {...} block
  • Javascript's regular expression engine's are implementation specific: e.g. it is possible to write "non-portable" regular expressions.

[updated a little in response to good comments; please see comments]

77
votes

I know I'm late to the party, but I just can't believe the + operator's usefulness hasn't been mentioned beyond "convert anything to a number". Maybe that's how well hidden a feature it is?

// Quick hex to dec conversion:
+"0xFF";              // -> 255

// Get a timestamp for now, the equivalent of `new Date().getTime()`:
+new Date();

// Safer parsing than parseFloat()/parseInt()
parseInt("1,000");    // -> 1, not 1000
+"1,000";             // -> NaN, much better for testing user input
parseInt("010");      // -> 8, because of the octal literal prefix
+"010";               // -> 10, `Number()` doesn't parse octal literals 

// A use case for this would be rare, but still useful in cases
// for shortening something like if (someVar === null) someVar = 0;
+null;                // -> 0;

// Boolean to integer
+true;                // -> 1;
+false;               // -> 0;

// Other useful tidbits:
+"1e10";              // -> 10000000000
+"1e-4";              // -> 0.0001
+"-12";               // -> -12

Of course, you can do all this using Number() instead, but the + operator is so much prettier!

You can also define a numeric return value for an object by overriding the prototype's valueOf() method. Any number conversion performed on that object will not result in NaN, but the return value of the valueOf() method:

var rnd = {
    "valueOf": function () { return Math.floor(Math.random()*1000); }
};
+rnd;               // -> 442;
+rnd;               // -> 727;
+rnd;               // -> 718;
75
votes

"Extension methods in JavaScript" via the prototype property.

Array.prototype.contains = function(value) {  
    for (var i = 0; i < this.length; i++) {  
        if (this[i] == value) return true;  
    }  
    return false;  
}

This will add a contains method to all Array objects. You can call this method using this syntax

var stringArray = ["foo", "bar", "foobar"];
stringArray.contains("foobar");
60
votes

To properly remove a property from an object, you should delete the property instead of just setting it to undefined:

var obj = { prop1: 42, prop2: 43 };

obj.prop2 = undefined;

for (var key in obj) {
    ...

The property prop2 will still be part of the iteration. If you want to completely get rid of prop2, you should instead do:

delete obj.prop2;

The property prop2 will no longer will make an appearance when you're iterating through the properties.

57
votes

with.

It's rarely used, and frankly, rarely useful... But, in limited circumstances, it does have its uses.

For instance: object literals are quite handy for quickly setting up properties on a new object. But what if you need to change half of the properties on an existing object?

var user = 
{
   fname: 'Rocket', 
   mname: 'Aloysus',
   lname: 'Squirrel', 
   city: 'Fresno', 
   state: 'California'
};

// ...

with (user)
{
   mname = 'J';
   city = 'Frostbite Falls';
   state = 'Minnesota';
}

Alan Storm points out that this can be somewhat dangerous: if the object used as context doesn't have one of the properties being assigned to, it will be resolved in the outer scope, possibly creating or overwriting a global variable. This is especially dangerous if you're used to writing code to work with objects where properties with default or empty values are left undefined:

var user = 
{
   fname: "John",
// mname definition skipped - no middle name
   lname: "Doe"
};

with (user)
{
   mname = "Q"; // creates / modifies global variable "mname"
}

Therefore, it is probably a good idea to avoid the use of the with statement for such assignment.

See also: Are there legitimate uses for JavaScript’s “with” statement?

51
votes

Methods (or functions) can be called on object that are not of the type they were designed to work with. This is great to call native (fast) methods on custom objects.

var listNodes = document.getElementsByTagName('a');
listNodes.sort(function(a, b){ ... });

This code crashes because listNodes is not an Array

Array.prototype.sort.apply(listNodes, [function(a, b){ ... }]);

This code works because listNodes defines enough array-like properties (length, [] operator) to be used by sort().

43
votes

Prototypal inheritance (popularized by Douglas Crockford) completely revolutionizes the way you think about loads of things in Javascript.

Object.beget = (function(Function){
    return function(Object){
        Function.prototype = Object;
        return new Function;
    }
})(function(){});

It's a killer! Pity how almost no one uses it.

It allows you to "beget" new instances of any object, extend them, while maintaining a (live) prototypical inheritance link to their other properties. Example:

var A = {
  foo : 'greetings'
};  
var B = Object.beget(A);

alert(B.foo);     // 'greetings'

// changes and additionns to A are reflected in B
A.foo = 'hello';
alert(B.foo);     // 'hello'

A.bar = 'world';
alert(B.bar);     // 'world'


// ...but not the other way around
B.foo = 'wazzap';
alert(A.foo);     // 'hello'

B.bar = 'universe';
alert(A.bar);     // 'world'
42
votes

Some would call this a matter of taste, but:

aWizz = wizz || "default";
// same as: if (wizz) { aWizz = wizz; } else { aWizz = "default"; }

The trinary operator can be chained to act like Scheme's (cond ...):

(cond (predicate  (action  ...))
      (predicate2 (action2 ...))
      (#t         default ))

can be written as...

predicate  ? action( ... ) :
predicate2 ? action2( ... ) :
             default;

This is very "functional", as it branches your code without side effects. So instead of:

if (predicate) {
  foo = "one";
} else if (predicate2) {
  foo = "two";
} else {
  foo = "default";
}

You can write:

foo = predicate  ? "one" :
      predicate2 ? "two" :
                   "default";

Works nice with recursion, too :)

41
votes

Numbers are also objects. So you can do cool stuff like:

// convert to base 2
(5).toString(2) // returns "101"

// provide built in iteration
Number.prototype.times = function(funct){
  if(typeof funct === 'function') {
    for(var i = 0;i < Math.floor(this);i++) {
      funct(i);
    }
  }
  return this;
}


(5).times(function(i){
  string += i+" ";
});
// string now equals "0 1 2 3 4 "

var x = 1000;

x.times(function(i){
  document.body.innerHTML += '<p>paragraph #'+i+'</p>';
});
// adds 1000 parapraphs to the document
33
votes

How about closures in JavaScript (similar to anonymous methods in C# v2.0+). You can create a function that creates a function or "expression".

Example of closures:

//Takes a function that filters numbers and calls the function on 
//it to build up a list of numbers that satisfy the function.
function filter(filterFunction, numbers)
{
  var filteredNumbers = [];

  for (var index = 0; index < numbers.length; index++)
  {
    if (filterFunction(numbers[index]) == true)
    {
      filteredNumbers.push(numbers[index]);
    }
  }
  return filteredNumbers;
}

//Creates a function (closure) that will remember the value "lowerBound" 
//that gets passed in and keep a copy of it.
function buildGreaterThanFunction(lowerBound)
{
  return function (numberToCheck) {
    return (numberToCheck > lowerBound) ? true : false;
  };
}

var numbers = [1, 15, 20, 4, 11, 9, 77, 102, 6];

var greaterThan7 = buildGreaterThanFunction(7);
var greaterThan15 = buildGreaterThanFunction(15);

numbers = filter(greaterThan7, numbers);
alert('Greater Than 7: ' + numbers);

numbers = filter(greaterThan15, numbers);
alert('Greater Than 15: ' + numbers);
32
votes

You can also extend (inherit) classes and override properties/methods using the prototype chain spoon16 alluded to.

In the following example we create a class Pet and define some properties. We also override the .toString() method inherited from Object.

After this we create a Dog class which extends Pet and overrides the .toString() method again changing it's behavior (polymorphism). In addition we add some other properties to the child class.

After this we check the inheritance chain to show off that Dog is still of type Dog, of type Pet, and of type Object.

// Defines a Pet class constructor 
function Pet(name) 
{
    this.getName = function() { return name; };
    this.setName = function(newName) { name = newName; };
}

// Adds the Pet.toString() function for all Pet objects
Pet.prototype.toString = function() 
{
    return 'This pets name is: ' + this.getName();
};
// end of class Pet

// Define Dog class constructor (Dog : Pet) 
function Dog(name, breed) 
{
    // think Dog : base(name) 
    Pet.call(this, name);
    this.getBreed = function() { return breed; };
}

// this makes Dog.prototype inherit from Pet.prototype
Dog.prototype = new Pet();

// Currently Pet.prototype.constructor
// points to Pet. We want our Dog instances'
// constructor to point to Dog.
Dog.prototype.constructor = Dog;

// Now we override Pet.prototype.toString
Dog.prototype.toString = function() 
{
    return 'This dogs name is: ' + this.getName() + 
        ', and its breed is: ' + this.getBreed();
};
// end of class Dog

var parrotty = new Pet('Parrotty the Parrot');
var dog = new Dog('Buddy', 'Great Dane');
// test the new toString()
alert(parrotty);
alert(dog);

// Testing instanceof (similar to the `is` operator)
alert('Is dog instance of Dog? ' + (dog instanceof Dog)); //true
alert('Is dog instance of Pet? ' + (dog instanceof Pet)); //true
alert('Is dog instance of Object? ' + (dog instanceof Object)); //true

Both answers to this question were codes modified from a great MSDN article by Ray Djajadinata.

31
votes

You may catch exceptions depending on their type. Quoted from MDC:

try {
   myroutine(); // may throw three exceptions
} catch (e if e instanceof TypeError) {
   // statements to handle TypeError exceptions
} catch (e if e instanceof RangeError) {
   // statements to handle RangeError exceptions
} catch (e if e instanceof EvalError) {
   // statements to handle EvalError exceptions
} catch (e) {
   // statements to handle any unspecified exceptions
   logMyErrors(e); // pass exception object to error handler
}

NOTE: Conditional catch clauses are a Netscape (and hence Mozilla/Firefox) extension that is not part of the ECMAScript specification and hence cannot be relied upon except on particular browsers.

31
votes

Off the top of my head...

Functions

arguments.callee refers to the function that hosts the "arguments" variable, so it can be used to recurse anonymous functions:

var recurse = function() {
  if (condition) arguments.callee(); //calls recurse() again
}

That's useful if you want to do something like this:

//do something to all array items within an array recursively
myArray.forEach(function(item) {
  if (item instanceof Array) item.forEach(arguments.callee)
  else {/*...*/}
})

Objects

An interesting thing about object members: they can have any string as their names:

//these are normal object members
var obj = {
  a : function() {},
  b : function() {}
}
//but we can do this too
var rules = {
  ".layout .widget" : function(element) {},
  "a[href]" : function(element) {}
}
/* 
this snippet searches the page for elements that
match the CSS selectors and applies the respective function to them:
*/
for (var item in rules) {
  var elements = document.querySelectorAll(rules[item]);
  for (var e, i = 0; e = elements[i++];) rules[item](e);
}

Strings

String.split can take regular expressions as parameters:

"hello world   with  spaces".split(/\s+/g);
//returns an array: ["hello", "world", "with", "spaces"]

String.replace can take a regular expression as a search parameter and a function as a replacement parameter:

var i = 1;
"foo bar baz ".replace(/\s+/g, function() {return i++});
//returns "foo1bar2baz3"
29
votes

You can use objects instead of switches most of the time.

function getInnerText(o){
    return o === null? null : {
        string: o,
        array: o.map(getInnerText).join(""),
        object:getInnerText(o["childNodes"])
    }[typeis(o)];
}

Update: if you're concerned about the cases evaluating in advance being inefficient (why are you worried about efficiency this early on in the design of the program??) then you can do something like this:

function getInnerText(o){
    return o === null? null : {
        string: function() { return o;},
        array: function() { return o.map(getInnerText).join(""); },
        object: function () { return getInnerText(o["childNodes"]; ) }
    }[typeis(o)]();
}

This is more onerous to type (or read) than either a switch or an object, but it preserves the benefits of using an object instead of a switch, detailed in the comments section below. This style also makes it more straightforward to spin this out into a proper "class" once it grows up enough.

update2: with proposed syntax extensions for ES.next, this becomes

let getInnerText = o -> ({
    string: o -> o,
    array: o -> o.map(getInnerText).join(""),
    object: o -> getInnerText(o["childNodes"])
}[ typeis o ] || (->null) )(o);
25
votes

Be sure to use the hasOwnProperty method when iterating through an object's properties:

for (p in anObject) {
    if (anObject.hasOwnProperty(p)) {
        //Do stuff with p here
    }
}

This is done so that you will only access the direct properties of anObject, and not use the properties that are down the prototype chain.

23
votes

Private variables with a Public Interface

It uses a neat little trick with a self-calling function definition. Everything inside the object which is returned is available in the public interface, while everything else is private.

var test = function () {
    //private members
    var x = 1;
    var y = function () {
        return x * 2;
    };
    //public interface
    return {
        setx : function (newx) {
            x = newx;
        },
        gety : function () {
            return y();
        }
    }
}();

assert(undefined == test.x);
assert(undefined == test.y);
assert(2 == test.gety());
test.setx(5);
assert(10 == test.gety());