Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
(NOTE: This has been since improved to handle negative values at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice#Streamlining_cross-browser_behavior ); Polyfill for "fixing" IE's lack of support (IE < 9) for applying slice on host objects like NamedNodeMap, NodeList, and HTMLCollection (technically, s…
<!DOCTYPE html>
<body id="body" class="abc"><script src="Array.prototype.slice.js"></script><script src="testing-Array.prototype.slice.js"></script>
</body>
/**
* Polyfill for "fixing" IE's lack of support (IE < 9) for applying slice
* on host objects like NamedNodeMap, NodeList, and HTMLCollection
* (technically, since host objects are implementation-dependent,
* IE hasn't needed to work this way, though I am informed this
* will be changing with ES6). Also works on strings,
* fixes IE to allow an explicit undefined for the 2nd argument
* (as in Firefox), and prevents errors when called on other
* DOM objects.
* @license MIT, GPL, do whatever you want
-* @see https://gist.github.com/brettz9/6093105
*/
(function () {
'use strict';
var _slice = Array.prototype.slice;
try {
_slice.call(document.documentElement); // Can't be used with DOM elements in IE < 9
}
catch (e) { // Fails in IE < 9
Array.prototype.slice = function (begin, end) {
var i, arrl = this.length, a = [];
if (this.charAt) { // Although IE < 9 does not fail when applying Array.prototype.slice
// to strings, here we do have to duck-type to avoid failing
// with IE < 9's lack of support for string indexes
for (i = 0; i < arrl; i++) {
a.push(this.charAt(i));
}
}
else { // This will work for genuine arrays, array-like objects, NamedNodeMap (attributes, entities, notations), NodeList (e.g., getElementsByTagName), HTMLCollection (e.g., childNodes), and will not fail on other DOM objects (as do DOM elements in IE < 9)
for (i = 0; i < this.length; i++) { // IE < 9 (at least IE < 9 mode in IE 10) does not work with node.attributes (NamedNodeMap) without a dynamically checked length here
a.push(this[i]);
}
}
return _slice.call(a, begin, end || a.length); // IE < 9 gives errors here if end is allowed as undefined (as opposed to just missing) so we default ourselves
};
}
}());
var body = document.getElementsByTagName('body')[0];
document.write( // Array through normal Array.call (standardized to allow explicit undefined second argument)
['a', 'b', 'c', 'd'].slice(0, undefined).splice(1, 2).toString() === 'b,c'
);
document.write( // Array through Array.prototype.slice.call
[].slice.call(['a', 'b', 'c', 'd']).splice(1, 2).toString() === 'b,c'
);
// Other objects through Array.prototype.slice.call
document.write( // String
[].slice.call('abcd').toString() === 'a,b,c,d'
);
document.write( // String
[].slice.call('abcd', 1, -1).toString() === 'b,c'
);
document.write( // NamedNodeMap
[].slice.call(body.attributes).toString() === '[object Attr],[object Attr]'
);
document.write( // NodeList
[].slice.call(body.childNodes).toString() === '[object HTMLScriptElement],[object HTMLScriptElement],[object Text]'
);
document.write( // HTMLCollection
[].slice.call(document.getElementsByTagName('HTML')).splice(0, 1).toString() === '[object HTMLHtmlElement]'
);
document.write( // Array-like object
[].slice.call({length: 3, 0: 'a', 1: 'b', 2: 'c'}).toString() === 'a,b,c'
);
document.write( // Array-like object, slice passed with arguments
[].slice.call({length: 3, 0: 'a', 1: 'b', 2: 'c'}, 1, -1).toString() === 'b'
);
@codefactor

This comment has been minimized.

Copy link

@codefactor codefactor commented Feb 12, 2015

This is broken when end is passed as 0, it is replaced with a.length and returns the entire array.

document.write(
    [].slice.call([0], 0, 0).join('') === '' // will be false in IE < 9, true every where else
);

I changed the code:

return _slice.call(a, begin, typeof end == 'number' ? end : (end || a.length));

This worked for me - there may be a more elegant way to do it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.