Skip to content

Instantly share code, notes, and snippets.

@brettz9
Last active February 18, 2021 06:54
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save brettz9/6093105 to your computer and use it in GitHub Desktop.
Save brettz9/6093105 to your computer and use it in GitHub Desktop.
(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
Copy link

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