How Internet Explorer 8 document mode affects JavaScript

In a previous post, I talked about Internet Explorer 8′s wide array of browser and document modes. Most people are pretty familiar with how the various document modes affect layout in terms of how CSS is implemented, but what has been lost is how the document mode affects the core JavaScript engine in the browser. These changes are somewhat subtle, but important to understand when you’re working with Internet Explorer 8.

A couple of years ago, Microsoft published a paper called, JScript Deviations from ES3, in which they outlined ways in which the JScript engine (the one power Internet Explorer’s JavaScript) had deviated from the ECMAScript 3 standard. These deviations are somewhat innocuous, but chances are that you’ve been bitten by one or more of them at some point in the past. In Microsoft’s attempt to make Internet Explorer 8 more standards-compliant, the same issues that arose around CSS also arose around JavaScript. They could fix the deviations in JScript, but if the browser were running in IE5 or IE7 document modes, there could be problems as these fixes might be incompatible with the code targeting those browsers.

Microsoft chose to create versioned features of the JScript engine for Internet Explorer 8. For IE5 and IE7 document modes, the JScript engine acts as it did in the actual Internet Explorer 7, complete with all deviations from ECMAScript 3. When in IE8 document mode, the deviations are gone and you get the full power of the JScript engine.

Native JSON

Internet Explorer 8′s JScript engine implements the native JSON object object as defined by ECMAScript 5. The object is only present, however, when the page is running in IE8 document mode. This includes the global JSON object as well as methods used for JSON functionality:

  • Date.prototype.toJSON()
  • Number.prototype.toJSON()
  • String.prototype.toJSON()
  • Boolean.prototype.toJSON()

The JSON object and these methods in IE5 or IE7 document mode are undefined.

Note: Even though Date.prototype.toJSON() is supported in IE8 document, Date.prototype.toISOString() is not implemented. This is strange because they return the same value.

DOM getters/setters

One of the more curious aspects of the JScript engine is that it implements ECMAScript 5 getters and setters, but only for DOM objects and not for native JavaScript objects. The implementation is made up of half-baked versions of Object.defineProperty() and Object.getOwnPropertyDescriptor() that primarily support the get and set properties. For example:

Object.defineProperty(document.body, "active", {
    set: function(value){
        document.body.className = (value !== false) ? "active" : "";
    },

    get: function(){
        return document.body.className == "active";
    }

});

var descriptor = Object.getOwnPropertyDescriptor(document.body, "innerHTML");
alert(descriptor.get);   //displays function

Both methods are only available in IE8 document mode and do not exist in other document modes.

Arrays

One of the areas where the JScript implementation really fell apart was in dealing with arrays. Arrays had the most deviations from the ECMAScript 3 standard and were a constant source of headaches for developers. First, if undefined is passed into join(), the argument was translated into the string “undefined” and that was used to concatenate the items. For example:

var colors = ["red", "green", "blue"];
alert(colors.join(undefined));    //"redundefinedgreenundefinedblue" in IE7

When running in IE8 document mode, a value of undefined is ignored and the default separator (a comma) is used.

The unshift() method, which pushes an item to the front of the array, also had a deviation in JScript. Instead of returning the length of the array after adding the item, it simply returned undefined. In IE8 document mode, this has been fixed so that unshift() correctly returns the array length.

The last big change to arrays is the ability to properly inherit from the Array type. Dean Edwards has a whole post about trying to create a subtype of Array and the problems he encountered. The biggest problem is that assigning an instance of Array to be another constructor’s prototype meant that the length property would no longer work. Consider the following:

function MyArray(){
}

MyArray.prototype = new Array();
MyArray.prototype.get = function(i){
    return this[i];
};

var colors = new MyArray();
colors.push("red");
colors.push("green");
colors.sort();
alert(colors.get(0));    //"green"
alert(colors.length);    //in IE7, outputs "0"; in IE8, outputs "2"

In Internet Explorer prior to 8, the length property of any Array type descendant didn’t change automatically, and so inheritance was only truly useful only for non-IE browsers. In IE8 document mode, though, the length property works as it does in other browsers while IE5 and IE7 document modes use the old deviated behavior.

Miscellaneous fixes

There’s a small group of fixes that can’t really be logically categorized but nonetheless help JScript come more into agreement with other JavaScript implementations. The first is that object literals now allow trailing commas. Prior to Internet Explorer 8, the following would cause a parse error:

var object = {
    name: "value",
};

The trailing comma after the last property value is explicitly allowed by ECMAScript 3 syntax and is allowed in all other browsers. IE8 document mode now also supports this syntax correctly (other document modes still throw the error).

Another nice enhancement is that IE8 document mode now allows access to characters in a string via bracket notation:

var s = "Hello world!";
alert(s[0]);    //"H"

This brings JScript into line with other JavaScript engines; IE5 and IE7 document modes will still return undefined.

Two other changes that likely don’t affect you but are worth noting:

  • Number.prototype.toPrecision() used to throw an error when undefined was passed in. IE8 document mode now defaults to calling Number.prototype.toString() in this case.
  • Error.prototype.toString() has been properly implemented to provide better error messages.

Conclusion

IE8 document mode offers a whole host of improvements over Internet Explorer 7 not just in CSS but also in JavaScript. If you’re looking to write the most standards-compliant code possible, make sure your page is being run on Internet Explorer 8 in IE8 document mode (see my previous post for details). Bringing JScript into line with other JavaScript engines is an incredibly important step. It’s too bad that these details were pretty much overlooked in the Internet Explorer 8 announcements.

Understanding JavaScript Promises E-book Cover

Demystify JavaScript promises with the e-book that explains not just concepts, but also real-world uses of promises.

Download the Free E-book!

The community edition of Understanding JavaScript Promises is a free download that arrives in minutes.