I'm trying to polyfill the array method includes() to work with IE8, which I need to support for a project and I don't want to use indexOf().
I know there's a polyfill, so I went to:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes#Polyfill
And included it at the top of my script.
IE8 has limited support for Object.defineProperty() so I polyfilled it as well: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperties#Polyfill
Lastly, I needed to polyfill Object.keys(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys#Polyfill
Put together, my polyfills are:
if (!Object.keys) {
Object.keys = (function() {
'use strict';
var hasOwnProperty = Object.prototype.hasOwnProperty,
hasDontEnumBug = !({ toString: null }).propertyIsEnumerable('toString'),
dontEnums = [
'toString',
'toLocaleString',
'valueOf',
'hasOwnProperty',
'isPrototypeOf',
'propertyIsEnumerable',
'constructor'
],
dontEnumsLength = dontEnums.length;
return function(obj) {
if (typeof obj !== 'function' && (typeof obj !== 'object' || obj === null)) {
throw new TypeError('Object.keys called on non-object');
}
var result = [], prop, i;
for (prop in obj) {
if (hasOwnProperty.call(obj, prop)) {
result.push(prop);
}
}
if (hasDontEnumBug) {
for (i = 0; i < dontEnumsLength; i++) {
if (hasOwnProperty.call(obj, dontEnums[i])) {
result.push(dontEnums[i]);
}
}
}
return result;
};
}());
}
function defineProperties(obj, properties) {
function convertToDescriptor(desc) {
function hasProperty(obj, prop) {
return Object.prototype.hasOwnProperty.call(obj, prop);
}
function isCallable(v) {
// NB: modify as necessary if other values than functions are callable.
return typeof v === 'function';
}
if (typeof desc !== 'object' || desc === null)
throw new TypeError('bad desc');
var d = {};
if (hasProperty(desc, 'enumerable'))
d.enumerable = !!desc.enumerable;
if (hasProperty(desc, 'configurable'))
d.configurable = !!desc.configurable;
if (hasProperty(desc, 'value'))
d.value = desc.value;
if (hasProperty(desc, 'writable'))
d.writable = !!desc.writable;
if (hasProperty(desc, 'get')) {
var g = desc.get;
if (!isCallable(g) && typeof g !== 'undefined')
throw new TypeError('bad get');
d.get = g;
}
if (hasProperty(desc, 'set')) {
var s = desc.set;
if (!isCallable(s) && typeof s !== 'undefined')
throw new TypeError('bad set');
d.set = s;
}
if (('get' in d || 'set' in d) && ('value' in d || 'writable' in d))
throw new TypeError('identity-confused descriptor');
return d;
}
if (typeof obj !== 'object' || obj === null)
throw new TypeError('bad obj');
properties = Object(properties);
var keys = Object.keys(properties);
var descs = [];
for (var i = 0; i < keys.length; i++)
descs.push([keys[i], convertToDescriptor(properties[keys[i]])]);
for (var i = 0; i < descs.length; i++)
Object.defineProperty(obj, descs[i][0], descs[i][1]);
return obj;
}
if (!Array.prototype.includes) {
alert('test');
defineProperties(Array.prototype, 'includes', {
value: function(searchElement, fromIndex) {
'use strict';
if (this === null) {
throw new TypeError('"this" is null or not defined');
}
// 1. Let O be ? ToObject(this value).
var o = Object(this);
// 2. Let len be ? ToLength(? Get(O, "length")).
var len = o.length >>> 0;
// 3. If len is 0, return false.
if (len === 0) {
return false;
}
// 4. Let n be ? ToInteger(fromIndex).
// (If fromIndex is undefined, this step produces the value 0.)
var n = fromIndex | 0;
// 5. If n ≥ 0, then
// a. Let k be n.
// 6. Else n < 0,
// a. Let k be len + n.
// b. If k < 0, let k be 0.
var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
function sameValueZero(x, y) {
return x === y || (typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y));
}
// 7. Repeat, while k < len
while (k < len) {
// a. Let elementK be the result of ? Get(O, ! ToString(k)).
// b. If SameValueZero(searchElement, elementK) is true, return true.
if (sameValueZero(o[k], searchElement)) {
return true;
}
// c. Increase k by 1.
k++;
}
// 8. Return false
return false;
}
});
}
To test the above script, I did:
var arr = ["one", "two", "three"];
alert( arr.includes('two') );
IE8 throws this error:
Object doesn't support this property or method.
I thought that by using polyfills, I would be able to add support for array includes() to IE8. What am I doing wrong? Any corrections or links to other polyfills are welcomed. No jQuery or other libraries. I just want to add support for includes() to IE.
You can simply use Array#indexOf
to polyfill Array#includes
.
For IE8, you will also need to polyfill Array#indexOf
as it was only implemented in IE9.
if(!Array.prototype.includes){
//or use Object.defineProperty
Array.prototype.includes = function(search){
return !!~this.indexOf(search);
}
}
if(!Array.prototype.indexOf){
Array.prototype.indexOf = (function(Object, max, min){
"use strict";
return function indexOf(member, fromIndex) {
if(this===null||this===undefined)throw TypeError("Array.prototype.indexOf called on null or undefined");
var that = Object(this), Len = that.length >>> 0, i = min(fromIndex | 0, Len);
if (i < 0) i = max(0, Len+i); else if (i >= Len) return -1;
if(member===void 0){ for(; i !== Len; ++i) if(that[i]===void 0 && i in that) return i; // undefined
}else if(member !== member){ for(; i !== Len; ++i) if(that[i] !== that[i]) return i; // NaN
}else for(; i !== Len; ++i) if(that[i] === member) return i; // all else
return -1; // if the value was not found, then return -1
};
})(Object, Math.max, Math.min);
}
Array.prototype.includes = null;
Array.prototype.indexOf = null;
if(!Array.prototype.includes){
console.log('Polyfilled Array.prototype.includes');
//or use Object.defineProperty
Array.prototype.includes = function(search){
return !!~this.indexOf(search);
}
}
if(!Array.prototype.indexOf){
console.log("Polyfilled Array.prototype.indexOf");
Array.prototype.indexOf = (function(Object, max, min){
"use strict";
return function indexOf(member, fromIndex) {
if(this===null||this===undefined)throw TypeError("Array.prototype.indexOf called on null or undefined");
var that = Object(this), Len = that.length >>> 0, i = min(fromIndex | 0, Len);
if (i < 0) i = max(0, Len+i); else if (i >= Len) return -1;
if(member===void 0){ for(; i !== Len; ++i) if(that[i]===void 0 && i in that) return i; // undefined
}else if(member !== member){ for(; i !== Len; ++i) if(that[i] !== that[i]) return i; // NaN
}else for(; i !== Len; ++i) if(that[i] === member) return i; // all else
return -1; // if the value was not found, then return -1
};
})(Object, Math.max, Math.min);
}
var obj = {x: 1, y: 2};
var arr = [1, 'what', obj];
console.log('Array includes 1:',arr.includes(1));
console.log('Array includes \'what\':', arr.includes('what'));
console.log('Array includes obj:', arr.includes(obj));
console.log('Array includes 3:', arr.includes(3));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With