ECMA-262, 5th Edition

A survey of the latest JavaScript specification

Take a look at the history of the ECMAScript specification while also learning about many of its important new features and concepts.

Share:

Rob Larsen, Interface Architect, Isobar

Rob Larsen photoRob Larsen has more than 11 years of experience building and designing websites and web applications. Currently, he's an interface architect at Isobar, working with HTML5, CSS3, and other emerging technologies for some of the world's largest brands. Rob writes about the web and web technologies at his blog, HTML + CSS + JavaScript, and you can reach him at rob@htmlcssjavascript.com.



12 April 2011

Also available in Chinese Japanese

The standard published under the dry title ECMA-262, 5th Edition (hereafter referred to as ES5), is the latest version of the ECMAScript specification. ECMAScript is the standard upon which JavaScript—the single most important language on the web today—is built. Because the language also serves as the basis for Adobe ActionScript (in addition to other flavors), it's fair to say that the ECMAScript standard is central to the present and future of interactivity on the web.

Published in December 2009, ES5 represents an incremental improvement in the language, arrived at through a lengthy, and occasionally contentious, process. Still, whatever friction there might have been in the development of the specification, the end result contains some excellent enhancements to the language. This article outlines the long history of the specification's development, then steps through many of its important new features and concepts.

Background

Not surprisingly, considering the various companies and individual personalities involved in the development of this increasingly important specification, the path to ES5 was a long and varied one. The organization formerly known as the European Computer Manufacturers Association (ECMA)—now simply known by the non-acronym name Ecma—is an international computer and information systems standards organization. The majority of web standards dealt with are housed at the W3C, including the closely related DOM specification. JavaScript/ECMAScript, however, is not. In his epic series of presentations on JavaScript, Yahoo!'s JavaScript architect, Douglas Crockford, offers a colorful explanation for this circumstance.

The time is 1996, and JavaScript is a wildly popular browser innovation from Netscape that Microsoft®, playing catch-up in the web browser space, reverse-engineered and presented as a feature in its Windows® Internet Explorer® browser. Crockford explains:

"Netscape looked at [JScript] with alarm: Oh no, we're going to be embraced and extended, so we need to make a standard out of this. So, they went to W3C and said okay, we've got a language for you to standardize. W3C had been waiting for a long time for an opportunity to tell Netscape to go to hell, so they told Netscape to go to hell.
"Netscape went around to ISO and other places looking for a place where they could buy a standard, and they eventually ended up at the European Computer Manufacturers Association, which is a long way to go for a California software company, but that's where they ended up."

The good news is, even with such a vagabond origin story, the standardization of ECMAScript has served the web development community at large well—even if Netscape itself didn't fare quite as well.

The path to the 5th edition

Before ES5, the last major version of the specification was the third edition, published in December 1999. Work on the edition that was originally meant to be ES4 commenced after the third edition was published. An interim report was published in 2003, which lead to implementation work by Adobe and Microsoft, but progress on the main standard stalled until the fall of 2005, when the Task Group 1 of Ecma Technical Committee 39 (TG1) began meeting regularly.

In hindsight, this was an auspicious time to have restarted the process, as the Asynchronous JavaScript + XML (Ajax)-led renaissance of JavaScript was just beginning in earnest. Jesse James Garrett's seminal article, "Ajax: A New Approach to Web Applications," (see Resources) had been published in February of that year, and the technical design paradigms that you take for granted now were being forged at a furious pace.

Basing their work on ES3 (the report published in 2003) and lessons learned from Adobe and Microsoft's implementations, TG1 moved toward what was to be a radical reworking of the language. It's outside of the scope of this article to go into the details of the proposed specification, but the ambitious goals of the specification lead to controversy in the working group itself.

In 2007, this internal strife—a conflict that touched on the fundamental goals of the specification—was made public. The publicly visible split was between Chris Wilson of Microsoft and Brendan Eich of Mozilla, the original designer of the language. The two men represented opposing viewpoints of what the specification should aim to be.

Eich was the visible representative of the proponents of the radical enhancements of the language then proposed for ES4. Wilson represented those that felt that the changes amounted to "breaking the web," because they represented too dramatic a change from the existing specification. ES4 at that time wouldn't have been backwards compatible—a valid concern echoed in the design decisions made in the What-WG's work on the HTML5 specification.

This split effectively broke the standards group into two pieces: ES4 dissenters (led by Microsoft and Yahoo!) broke off and began working on ECMAScript 3.1, a specification designed to provide incremental improvement and bug fixes. Meanwhile, Eich and other ES4 proponents were still working on the ES4 specification. Recognizing the negative effects of the split and presumably the growing importance of ECMAScript to the future of the web, the standards group got together in July 2008 (in what's been dubbed the "Oslo Meeting") to patch over their differences. Thankfully for us, TG1 emerged from the meeting with a new accord.

ES5 and harmony

The plan, announced by Eich on the respective group's mailing lists, was to focus immediate effort on the 3.1 specification, and then move on to a scaled-back (at least compared to ES4), but still ambitious, reworking of the language called ES-harmony. That 3.1 branch eventually became ES5.

Now that you have a history of the specification, let's take a look at what all that hard work and occasional strife have produced.


New features and concepts of ES5

Several areas have received attention in this latest edition of the standard. The edition contains two major areas of importance and a few smaller, but still useful, changes and additions. I've provided code samples based on support for the new ES5 features. To try out the majority of these samples yourself, you must be running Internet Explorer version 9, Mozilla Firefox version 4, or Google Chrome version 6 or later. You'll also need a console open.

Note: As of this writing, Firefox 4 is the only browser that supports strict mode. For more up-to-date compatibility information, check out the ES5 Compatibility Table (see Resources for a link).


Strict mode

One of the more interesting pieces in the new specification is the introduction of strict mode, an opt-in mechanism that allows developers to use a restricted, but cleaner, subset of the JavaScript language. To invoke the spirit of Doug Crockford, strict mode is designed to fix or limit some of the language's most egregious "bad parts."

Strict mode can be implemented at either the script or function level. This is nice, because it allows module and library authors to choose to write strict code without affecting the rest of the environment. The one thing to keep in mind is that concatenating strict and non-strict scripts for performance reasons can have unintended consequences. See Amazon's bug in the Resources section for an example.

You invoke strict mode at the script level by including the statement use strict before any other statements in a file. Listing 1 provides an example.

Listing 1. Invoking strict mode at the script level
"use strict";
var myNamespace = {
    myMethod : function(){
    	//strict code
	}
}

At the function level, the mode is similarly invoked by including the statement use strict inside the function body before any other statement, as shown in Listing 2.

Listing 2. Invoking strict mode at the function level
function getStrict(){
	"use strict";
	//strict code
}

It's interesting to note that the syntax used to invoke strict mode is just a string expression statement, which means that by itself it won't do any harm to include it in your code right now. Browsers that understand it will turn on the subset. Those that don't will read it as an expression statement, ignore it, and then move on to the next line in the code. Of course, there are other concerns with invoking strict mode when only a minority of browsers support it, but the Use Strict Directive itself isn't one of them.


Strict mode in practice

The following sections outline the effect of strict mode on your code. Although it's not an exhaustive examination of every aspect of strict mode, it touches on the major themes of the new mode. The best way to understand strict mode is to work with these examples in a browser that offers support.

For the boldest, you can drop the directive into the head of one of your existing scripts and see how many errors pile up (or not, if you're already careful enough to avoid these pitfalls).

Noisy errors and the death of accidental globals

One section that I'm particularly fond of in strict mode looks like the nitpicky parts of a code review. Strict mode turns several common negative coding patterns that would normally be ignored or fail silently in standard script into actual errors. The most common of these is the accidental creation of a global variable by assigning a value to an undeclared variable without the use of the var statement. In standard code, this is merely bad practice. In strict mode, it throws a reference error, as shown in Listing 3.

Listing 3. No accidental globals
function nopullution(){
	"use strict";
	myAccidentalGlobal = "polluting the global namespace is for losers";
}
nopullution();
>>>Error: assignment to undeclared variable myAccidentalGlobal

Accidental globals are also prevented by a change in the way the this keyword is bound in certain situations. For example, if a constructor function is called directly instead of with the new prefix, this will be bound to the global object. Strict mode binds this, in those situations, to undefined, preventing unexpected pollution of the global namespace.

In addition, actions that would simply fail silently, like deleting an undeletable property or repeating argument or property names, now throw errors. Examples of these are given in Listing 4.

Listing 4. Noisy errors
"use strict"
delete Array.prototype;

>>>Error: property "use strict";Array.prototype is non-configurable and
can't be deleted
"use strict"
var myObj ={
        dupe: 1,
        dupe :2
}
>>>Error: property name dupe appears more than once in object literal

Static binding

Strict mode also enforces static binding of variable names by doing away with the language features that relied on dynamic binding. It does this by prohibiting the use of the with statement by limiting the ability of eval to create variables in the calling context. In strict mode, eval is executed in a sandbox that is destroyed after the eval ends. One benefit of this is that JavaScript minification tools see compression improvements because they can optimize around static bindings.


Object enhancements

The second area of interest is a set of much-needed enhancements to the core Object. Object has been strengthened with several new features that add powerful, necessary tricks to the ECMAScript inheritance toolbox.

Object.create()

You use the Object.create method to create a new object with a specified prototype object and an additional properties object. This is a powerful new interface to object creation, inheritance, and reuse. With create(), inheritance can be set and an object enhanced—all in one cleanly defined interface. With the new features presented by Object properties available, JavaScript inheritance has become a much more straightforward endeavour. Listing 5 offers a simple example.

Listing 5. Using Object.create()
//create a simple, traditional object that has some properties
var marvelProto = {
    publisher : "Marvel Comics",
    founded : "1939",
    founder : "Martin Goodman",
    headquarters : "417 5th Avenue, New York, NY, U.S."
}

//create a new object that inherits properties from the simple object
//create() takes two arguments. the object that will serve
//as the new object's prototype and an optional set of 
//new properties to populate the new object 
var FantasticFour = Object.create(
    marvelProto,
    {
        title : {
            value : "Fantastic Four",
            
        },
        year : {
            value : "1961",
            
        }
    }
);
console.log(
    FantasticFour.title 
    +" was first published by "+
    FantasticFour.publisher 
    +" in "+ 
    FantasticFour.year
);

Property attributes

Enhancing the power of create() is a set of new property attributes that allow for much finer control of inheritance. You saw one in the previous example: the explicitly labeled value. Three other Boolean flags greatly enhance the flexibility and control you will have over your Objects:

  • You can change the value of writable properties.
  • enumerable indicates whether the property is visible to for...in loops and in the new Object.keys() method.
  • You can delete configurable properties and alter their attributes.

The previous example can be improved with the new property attributes to lock down several attributes that shouldn't change after they are defined. This new version is visible in Listing 6.

Listing 6. Leveraging property attributes to define objects
var marvelProto = Object.create(
    //pass in the default object as a template
    {},
    {
    //and then create more finely defined properties    
        publisher : {
            value  : "Marvel Comics",
          //yes, we want it exposed
            enumerable: true,
          //Theoretically, the value might change  
            writable: true,
          //but it can't be deleted/edited  
            configurable: false
        },
        founded : {
            value : "1939",
            enumerable: true,
                //this won't change, so we stop it from being overwritten
            writable: false,
            configurable: false
        },
        founder : {
            value : "Martin Goodman",
            enumerable: true,
            writable: false,
            configurable: false
        },
        headquarters : {
            value : "417 5th Avenue, New York, NY, U.S.",
            enumerable: true,
            //we might need to edit at some point
            writable: true,
            configurable: false
        }
    }
);
var FantasticFour = Object.create(
    marvelProto,
    {
        title : {
            value : "Fantastic Four",
            enumerable: true,
            writable: false,
            configurable: false
        },
        year : {
            value : "1961",
            enumerable: true,
            writable: false,
            configurable: false
        }
    }
);
console.log(
    FantasticFour.title 
    +" was first published by "+
    FantasticFour.publisher 
    +" in "+ 
    FantasticFour.year
);

Lockdown methods

Continuing the trend of being able to fine-tune and control Objects, ES5 has created three new methods that allow differing levels of "lockdown" to be applied to an object. These powerful, much-needed tools significantly increase the predictability of ECMAScript programs.

Note: Strict mode is used throughout these examples to force errors to be thrown when trying to perform actions prevented by the lockdown methods.

Object.preventExtensions() and Object.isExtensible()

The first of these lockdown methods is Object.preventExtensions(), which stops any new named properties from being added to an object. Object.isExtensible() tests whether named properties can be added to an object. These methods are illustrated in Listing 7.

Listing 7. Using Object.preventExtensions() and Object.isExtensible()
"use strict" 
var marvelProto = Object.create(
    //pass in the default object as a template
    {},
    {
        publisher : {
            value  : "Marvel Comics",
            enumerable: true,
            writable: false,
            configurable: false
        }
       /*...OTHER PROPERTIES*/
    }
);
//Let's see if we can add some more info to the object
if (Object.isExtensible(marvelProto)){
    //true
    marvelProto.flagshipCharater = "Spider-Man";
};

//Stop extensions
Object.preventExtensions(marvelProto);

//Adding an Editor in Chief field throws an error
marvelProto.editorInChief = "Axel Alonso";
>>>TypeError: Can't add property editorInChief, object is not extensible

Object.seal() and Object.isSealed()

Object.seal first calls Object.preventExtensions() to prevent new properties from being added, and then sets the configurable flag of all object properties to false. This lets you lock down an object for all but its values, making it predictable to use as a data store. Looping through the values of a sealed data object is now a much more predictable task, especially when paired with the enumerable flag. Object.isSealed() tests whether an object is configurable. Listing 8 shows an example of these methods in action.

Listing 8. Using Object.seal() and Object.isSealed()
"use strict" 
var marvelProto = Object.create(
    //pass in the default object as a template
    {},
    {
        publisher : {
            value  : "Marvel Comics",
            enumerable: true,
            writable: false,
            configurable: false
        },
       /*...OTHER PROPERTIES*/
        //optional properties
        flagshipCharacter : {
            value  : "Spider-Man",
            enumerable: true,
            writable: false,
            configurable: true
        },
        editorInChief : {
            value  : "Axel Alonso",
            enumerable: true,
            writable: false,
            configurable: true
        }
    }
);

//Can we delete configurable properties?
if (!Object.isSealed(marvelProto)){
    //we can
    delete marvelProto.flagshipCharacter;
};

//Seal the object
Object.seal(marvelProto);

//deleting the Editor in Chief field throws an error
delete marvelProto.editorInChief;
>>>Error: property "use strict";marvelProto.editorInChief is 
		non-configurable and can't be deleted

Object.freeze() and Object.isFrozen()

Object.freeze calls Object.seal() to stop configuration of an object, and then sets the writeable flag of all object properties to false, providing a perfectly static object. In environments where multiple sources are interacting with data, the ability to completely freeze objects creates a level of predictability and safety that hasn't really been available before.

Object.isFrozen() tests whether the object is frozen. Listing 9 provides an example of this method in action.

Listing 9. Using Object.freeze() and Object.isFrozen()
"use strict" 
var marvelProto = Object.create(
    //pass in the default object as a template
    {},
    {
        publisher : {
            value  : "Marvel Comics",
            enumerable: true,
            writable: false,
            configurable: false
        },
        //optional properties
        flagshipCharacter : {
            value  : "Spider-Man",
            enumerable: true,
            writable: false,
            configurable: true
        }
    }
);

//Can we write writeable properties?
if (!Object.isFrozen(marvelProto)){
    //we can
    marvelProto.flagshipCharacter = "Iron Man";
};

//Seal the object
Object.freeze(marvelProto);

//Changing the Flagship Character throws an error
marvelProto.flagshipCharacter = "Wolverine";
>>>Error: "use strict";marvelProto.flagshipCharacter is read-only

Object.getPrototypeOf()

The new method Object.getPrototypeOf() returns the prototype of an object. Its value is equivalent to the nonstandard Object.__proto__ property.

Object.keys() and Object.getOwnPropertyNames()

The Object.keys() method returns an array of strings representing the names of an object's own enumerable properties, meaning properties defined directly on the object being surveyed whose enumerable flag is set to true. Object.getOwnPropertyNames() is similar, but also includes properties that have the enumerable flag set to false. Both of these methods are illustrated in Listing 10.

Listing 10. Using Object.keys() and Object.getOwnPropertyNames()
var USComicPublishers = {
    countryOfOrigin : {
        value  : "USA",
        enumerable: true,
        writable: false,
        configurable: false
    },
    medium : {
        value  : "comic books",
        enumerable: true,
        writable: false,
        configurable: false
    }
}
var marvelProto = Object.create(
//inherits properties from another Object
    USComicPublishers,
    {
        publisher : {
            value  : "Marvel Comics",
            enumerable: true,
            writable: false,
            configurable: false
        },
        founded : {
            value : "1939",
            enumerable: true,
            writable: false,
            configurable: false
        },
        founder : {
            value : "Martin Goodman",
            enumerable: true,
            writable: false,
            configurable: false
        },
        headquarters : {
            value : "417 5th Avenue, New York, NY, U.S.",
            enumerable: true,
            writable: true,
            configurable: false
        },
        launchComic : {
            value : function(){
                /*fancy code to create a new comic series
                this isn't data we want to expose when we inspect
                inherited objects */
                return true;
            },
            enumerable: false,
            writable: true,
            configurable: false
        }
    }
);

//inherits medium from parent, as expected
console.log(marvelProto.medium.value);
>>>comic books

//Our function is available
console.log(marvelProto.launchComic());
>>>true

//BUT... keys returns ONLY properties on object itself
//inherited properties are ignored
//launchComic (enumerable:false) is also skipped
console.log(Object.keys(marvelProto));
>>>["publisher", "founded", "founder", "headquarters"]

//getOwnPropertyNames also operates only on 
//properties of the object itself, but it
//also includes properties that have the
//enumerable flag set to false 
console.log(Object.getOwnPropertyNames(marvelProto);
>>>["launchComic", "founder", "founded", "headquarters", "publisher"]

Accessors (getters and setters)

Get and set bind an object property to a function that will be called when there's an attempt to access or write a property's value. Get takes zero arguments; set takes one (the value to set.) Both of these elements are illustrated in Listing 11.

Listing 11. ECMAScript getters and setters
var marvelProto = Object.create(
    //pass in the default object as a template
    {},
    {
        publisher : {
            value  : "Marvel Comics",
            enumerable: true,
            writable: false,
            configurable: false
        },
   /*OTHER PROPERTIES*/
    }
);
    
var FantasticFour = Object.create(
    marvelProto,
    {
        title : {
            value : "Fantastic Four",
            
        },
        year : {
            value : "1961",
            
        }
    }
);

//Use Object.defineProperty to set the getters and setters
//Alternatively, this could be set in the Object.create above
Object.defineProperty(FantasticFour, "bestIssue", {
    get: function () { return fave; },
    set: function (num) {
            fave = "The best single issue of Fantastic Four is issue #" + num;
        }
    }
);

FantasticFour.bestIssue = 51;
console.log(FantasticFour.bestIssue);
>>>The best single issue of Fantastic Four is #51

Array methods

Another area that received a lot of attention in the new specification is the array. The changes here aren't quite as fundamental or as powerful as the enhancements to Object, but there are many new methods worth noting.

Array.forEach()

The Array.forEach function takes a single argument: a function to be executed once for every element in an array. The function executed is passed three arguments: the specific element being accessed, the index of the element, and the array itself. Listing 12 shows a simple use of this convenience method.

Note: This method is significantly slower than an equivalent for loop because of the overhead of running a separate function every time. For every step, a new execution context is created and destroyed, and another level is added to the scope chain. Those add up.

Listing 12. Array.forEach() example
 var arr = [8, 10, 13, 10, 8, 1, 5];
function logger(element, index, array) {
    console.log("The value of the element at index " + index + " is " + element); 
}
arr.forEach(logger);
>>>The value of the element at index 0 is 8
>>>The value of the element at index 1 is 10
>>>The value of the element at index 2 is 13
>>>The value of the element at index 3 is 10
>>>The value of the element at index 4 is 8
>>>The value of the element at index 5 is 1
>>>The value of the element at index 6 is 5

Array.map()

Array.map returns a new array produced by calling a single function argument on every element in this array. The provided function receives the element in the array as a single argument. A simple example is provided in Listing 13.

Listing 13. Array.map() example
 var arr = [8, 10, 13, 10, 8, 1, 5];
function square(num){
    return num * num;    
}    
console.log(arr.map(square));  
>>>[64, 100, 169, 100, 64, 1, 25]

Array.reduce() and Array.reduceRight()

Reduce and reduceRight both execute a provided function against two elements of an array, working through the entire array to produce a single value. Array.reduce does this from left to right; Array.reduceRight() processes the array from right to left. Examples of both, including one that shows the importance of order, are shown in Listing 14.

Listing 14. Using Array.reduce() and Array.reduceRight()
var arr = [8, 10, 13, 10, 8, 1, 5];

console.log(arr.reduce(function(a, b){ return  a + b; }));           
>>>55

console.log(arr.reduce(function(a, b){ return  a +" "+ b; }));               
>>>8 10 13 10 8 1 5

console.log(arr.reduceRight(function(a, b){ return  a + b; }));           
>>>55

console.log(arr.reduceRight(function(a, b){ return  a +" "+ b; }));
>>>5 1 8 10 13 10 8

Array.filter()

The Array.filter() function returns a new array containing all elements that pass a test implemented by the single function argument. An example using a simple even/odd test is provided in Listing 15.

Listing 15. Using Array.filter()
var arr = [8, 10, 13, 10, 8, 1, 5];
function odd(element, index, array) {
     return (element%2);
}
console.log(arr.filter(odd));
>>>[13, 1, 5]

Array.every() and Array.some()

Both Array.every() and Array.some() test elements in an array against a single function argument. Array.every() returns true if all elements in the array pass the test implemented by the provided function. Array.some() returns true if any single element in the array passes the test implemented by the provided function. Examples of both, using a simple even/odd test, are provided in Listing 16.

Listing 16. Using Array.every() and Array.some()
var arr = [8, 10, 13, 10, 8, 1, 5];
function odd(element, index, array) {
     return (element%2);
}
console.log(arr.every(odd));
>>>false

console.log([1,3,5].every(odd))
>>>true

console.log(arr.some(odd));
>>>true

console.log([2,4,6].some(odd))
>>>false

Array.indexOf() and Array.lastIndexOf()

The Array.indexOf() and Array.lastIndexOf() functions both return an index at which a given element can be found in the array, or -1 if it's not present. Array.indexOf begins its search at the first element of the array or an optional position argument, and then searches forward to the end of the array, looking for a match. Array.lastIndexOf begins its search at the last element of the array or an optional position argument, and then searches backward to the beginning of the array, looking for a match. Simple examples of each are shown in Listing 17.

Listing 17. Using Array.indexOf() and Array.lastIndexOf()
 var arr = [8, 10, 13, 10, 8, 1, 5];
 
console.log("lastIndexOF is " + arr.lastIndexOf(10));
>>>lastIndexOF is 3

console.log("indexOF is " + arr.indexOf(10));
>>>indexOF is 1

JSON

JSON is a popular data-interchange format based on a subset of JavaScript syntax. ES5 standardizes JSON in a manner compatible with the reference json2.js implementation. It provides two methods: JSON.parse() and JSON.stringify().

JSON.parse()

The JSON.parse() method takes a string of JSON text and, if valid, converts it to an object or array. Listing 18 illustrates a simple use of JSON.parse(), converting a string back into an object.

Listing 18. Parsing a JSON string with JSON.parse()
var marvel = JSON.parse('{"publisher":"Marvel Comics", /*other properties*/}');
console.log(marvel.founder);
>>>Martin Goodman

JSON.stringify()

The JSON.stringiy() method converts an object to a JSON string. Listing 19 converts the example object into a string.

Listing 19. Converting an object to a string using JSON.stringify()
var marvelProto = Object.create(
    {},
    {
        publisher : {
            value  : "Marvel Comics",
            enumerable: true,
            writable: false,
            configurable: false
        }
        /*OTHER PROPERTIES*/
    }
);
console.log(JSON.stringify(marvelProto));
{"publisher":"Marvel Comics","founded":"1939","founder":"Martin Goodman"}

Other interesting new features

A couple of other new features are worth pointing out before the article wraps up.

Date.now()

The Date.now() method is a handy new method for getting the current time. This method replaces the common (new Date()).getTime() pattern. Listing 20 shows an example of Date.now() that tests the difference between the 500 millisecond argument sent to setTimeout and the actual clock time between executions of the function.

Listing 20. Using Date.now()
var datePrev = Date.now(),
        dateNow,
        count=0;
function later(){
        if (count < 5 ){
            dateNow = Date.now();
            console.log(datePrev - dateNow);
            datePrev=dateNow;
            setTimeout(later,500);
            count++;    
        }
}
later();

>>>0
>>>-487
>>>-500
>>>-512
>>>-500

Function.prototype.bind()

At its simplest, Function.prototype.bind, a popular innovation from Prototype.js, defines a function to be executed at some later date with a specified this value. In addition, arguments can be specified and bound to the function, allowing for customization of bound functions. A basic example of this powerful feature can be see in Listing 21.

Listing 21. A simplified Function.prototype.bind() example
//global values;
var favoriteIssue = 27,
        title = "Detective Comics";
var myFavoriteComic = {
        returnFavorite: function() {
                    if (arguments.length && arguments[0].newComic) {
                                this.favoriteIssue =arguments[0].newComic.favoriteIssue
                               this.title =arguments[0].newComic.title
                        };
        //what's this?
            console.log("this is "+this);
            //display the values
console.log("My favorite issue of "+ this.title +" is #" + this.favoriteIssue);
        },
        favoriteIssue: 168,
        title : "Daredevil"
};

//this is myFavoriteComic
//values are internal to the module
myFavoriteComic.returnFavorite();
>>>this is [object Object]
>>>My favorite issue of Daredevil is #168

//now we let this slip to the global object
var makeGlobal = myFavoriteComic.returnFavorite;
makeGlobal();
>>>this is [object Window]
>>>My favorite issue of Detective Comics is #27

//use bind to bind it to the correct this value
var boundToModule = makeGlobal.bind(myFavoriteComic);
boundToModule();
>>>this is [object Object]
>>>My favorite issue of Daredevil is #168

//pass in options to change the module values
var updatedFavoriteIssue = makeGlobal.bind(
myFavoriteComic,
{
	newComic :
		{        
			favoriteIssue:51, 
			title:"Fantastic Four"
		}

}
);
updatedFavoriteIssue()
>>>this is [object Object]
>>>My favorite issue of Fantastic Four is #51

Conclusion

Finishing with a method inspired by the work of a library is a fitting way to wrap up this article, for it's in the hands of library authors and other core JavaScript developers that the real power of the new features and functions in the specification will be uncovered. As more and more browsers come on board with ES5 support, and more developers dig in and start working with the latest version of the specification, you'll really start to get a feel for what's possible with these new tools. Considering the work browser vendors and developers have done on top of a 10-year-old specification, this modern revision looks like it will be the foundation of an exciting few years on the web.

Resources

Learn

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Web development on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Web development
ArticleID=645358
ArticleTitle=ECMA-262, 5th Edition
publish-date=04122011