Fixing JavaScript Array functions in Internet Explorer (indexOf, forEach, etc.) [closed] Fixing JavaScript Array functions in Internet Explorer (indexOf, forEach, etc.) [closed] javascript javascript

Fixing JavaScript Array functions in Internet Explorer (indexOf, forEach, etc.) [closed]


Many use the MDC fallback implementations (eg. for indexOf). They're generally rigorously standards-compliant, even to the extent of explicitly checking the types of all the arguments.

Unfortunately whilst it is clear that the authors regard this code as trivial and freely-usable, there doesn't seem to be an explicit licence-grant to put this in writing. The wiki as a whole is CC Attribution-ShareAlike, if that's an acceptable licence (though CC isn't designed for code as such).

js-methods looks OK in general, but is not as standards-compliant around the edges of how the functions are supposed to be (eg. undefined list items, functions that mutate the list). It's also full of other random non-standard methods, including some questionable ones like the dodgy stripTags and the incomplete UTF-8 codec (which is also a bit unnecessary given the unescape(encodeURIComponent) trick).

For what it's worth, here's what I use (which I hereby release into the public domain, if it can be said to be copyrightable at all). It's a bit shorter than the MDC versions as it doesn't attempt to type-sniff that you haven't done something silly like pass non-function callbacks or non-integer indexes, but apart from that it attempts to be standards-compliant. (Let me know if I've missed anything. ;-))

'use strict';// Add ECMA262-5 method binding if not supported natively//if (!('bind' in Function.prototype)) {    Function.prototype.bind= function(owner) {        var that= this;        if (arguments.length<=1) {            return function() {                return that.apply(owner, arguments);            };        } else {            var args= Array.prototype.slice.call(arguments, 1);            return function() {                return that.apply(owner, arguments.length===0? args : args.concat(Array.prototype.slice.call(arguments)));            };        }    };}// Add ECMA262-5 string trim if not supported natively//if (!('trim' in String.prototype)) {    String.prototype.trim= function() {        return this.replace(/^\s+/, '').replace(/\s+$/, '');    };}// Add ECMA262-5 Array methods if not supported natively//if (!('indexOf' in Array.prototype)) {    Array.prototype.indexOf= function(find, i /*opt*/) {        if (i===undefined) i= 0;        if (i<0) i+= this.length;        if (i<0) i= 0;        for (var n= this.length; i<n; i++)            if (i in this && this[i]===find)                return i;        return -1;    };}if (!('lastIndexOf' in Array.prototype)) {    Array.prototype.lastIndexOf= function(find, i /*opt*/) {        if (i===undefined) i= this.length-1;        if (i<0) i+= this.length;        if (i>this.length-1) i= this.length-1;        for (i++; i-->0;) /* i++ because from-argument is sadly inclusive */            if (i in this && this[i]===find)                return i;        return -1;    };}if (!('forEach' in Array.prototype)) {    Array.prototype.forEach= function(action, that /*opt*/) {        for (var i= 0, n= this.length; i<n; i++)            if (i in this)                action.call(that, this[i], i, this);    };}if (!('map' in Array.prototype)) {    Array.prototype.map= function(mapper, that /*opt*/) {        var other= new Array(this.length);        for (var i= 0, n= this.length; i<n; i++)            if (i in this)                other[i]= mapper.call(that, this[i], i, this);        return other;    };}if (!('filter' in Array.prototype)) {    Array.prototype.filter= function(filter, that /*opt*/) {        var other= [], v;        for (var i=0, n= this.length; i<n; i++)            if (i in this && filter.call(that, v= this[i], i, this))                other.push(v);        return other;    };}if (!('every' in Array.prototype)) {    Array.prototype.every= function(tester, that /*opt*/) {        for (var i= 0, n= this.length; i<n; i++)            if (i in this && !tester.call(that, this[i], i, this))                return false;        return true;    };}if (!('some' in Array.prototype)) {    Array.prototype.some= function(tester, that /*opt*/) {        for (var i= 0, n= this.length; i<n; i++)            if (i in this && tester.call(that, this[i], i, this))                return true;        return false;    };}

Other ECMA262-5 methods not implemented here include Array reduce/reduceRight, the JSON ones and the few new Object methods that can be reliably implemented as JS functions.


Kris Kowal has compiled a small library that acts as a shim for ECMAScript 5 functions that may be missing from the browser's implementation. Some of the functions have been revised numerous times by other people to be optimized for speed and to work around browser bugs. The functions are written to follow the specification as closely as possible.

es5-shim.js was released under the MIT license, the Array.prototype extensions are near the top and you can chop and remove any functions you don't need quite easily. I also suggest you minify the script as the comments make it much larger than it needs to be.