[英]How to Polyfill Array.prototype.includes() for IE8
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().我正在尝试填充数组方法 includes() 以与 IE8 一起使用,我需要支持一个项目并且我不想使用 indexOf()。
I know there's a polyfill, so I went to:我知道有一个 polyfill,所以我去了:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes#Polyfill 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 IE8 对 Object.defineProperty() 的支持有限,所以我也对它进行了 polyfill: 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最后,我需要 polyfill Object.keys(): https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys#Polyfill
Put together, my polyfills are:放在一起,我的 polyfills 是:
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: IE8 抛出此错误:
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.我认为通过使用 polyfills,我可以向 IE8 添加对数组 includes() 的支持。 What am I doing wrong?
我究竟做错了什么? Any corrections or links to other polyfills are welcomed.
欢迎任何更正或指向其他 polyfill 的链接。 No jQuery or other libraries.
没有 jQuery 或其他库。 I just want to add support for includes() to IE.
我只想为 IE 添加对 includes() 的支持。
You can simply use Array#indexOf
to polyfill Array#includes
.您可以简单地使用
Array#indexOf
来填充Array#includes
。
For IE8, you will also need to polyfill Array#indexOf
as it was only implemented in IE9.对于 IE8,您还需要对
Array#indexOf
因为它仅在 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));
use arr.indexOf('two')使用 arr.indexOf('two')
if return 1 is because it exists, and -1 does not exist如果返回1是因为它存在,而-1不存在
Unfortunately I don't have a way to test in IE8, but I think there are a couple of things going on here -- first, you don't need to define defineProperties(obj, properties)
because neither the Object.keys
nor Array.prototype.includes
polyfills use it -- they are both self-contained.不幸的是,我没有办法在 IE8 中进行测试,但我认为这里有几件事情要做——首先,你不需要定义
defineProperties(obj, properties)
因为Object.keys
和Array.prototype.includes
使用它——它们都是独立的。 The fact that they are self-contained also means that you don't need to include the Object.keys
polyfill.它们是自包含的这一事实也意味着您不需要包含
Object.keys
polyfill。
I would suggest only using the includes Array.prototype.includes
if that is all you need.如果这就是你所需要的,我建议只使用包含
Array.prototype.includes
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.