本篇文章主要是介绍ES2016(ES7)的其中一个数组特性includes,通过实例来对比一下该函数与indexOf的区别以及如何使用es5来实现该特性。
函数介绍
Array.prototype.includes是在ES2016版本中被引入的一个数组函数,该函数允许我们查询一个对象是否被包含在数组中,可能我们经常使用的传统的方式是indexOf来查询,indexOf通过返回值是否等于-1来获得查询对象是否被该数组包含。而includes则是通过返回true或者false来得出结果,对于只是查询是否包含,语义显得更清晰一些。
var boolean = array.includes(searchElement[, fromIndex])
参数列表:
searchElement:搜索的对象内容。fromIndex:可选参数,类似于indexOf的第二个参数,指定搜素开始的位置,缺省为0。
函数实例
如果仅仅是与indexOf返回值略有不同,好像存在的意义也不大。但是通过includes具有一些新的比较规则,我们通过以下的实例来介绍以下。
以下实例均可以在最新的chrome,firefox浏览器中测试。
[1,2,3].includes(2)
true
[1,2,3].includes(4)
false
[1,2,3].includes(3,3)
false
[1,2,3].includes(3,2)
true
[1,2,NaN].includes(NaN)
true
大家可以看到我们可以通过includes来测试一个数组中是否包含NaN,这样的比较如果使用indexOf则返回
[1,2,NaN].indexOf(NaN)
-1
可见函数实现上includes进行了一些深度的测试与比较,包含了NaN对象的判定。
函数实现
如果在浏览器环境中我们想使用该函数的话,最好是写一些Polyfill来检测浏览器的支持程度,对于不支持的浏览器我们需要实现该函数,以备后面的程序中使用。MDN上已经对于该函数做了实现,如下面代码所示。
if (!Array.prototype.includes) {
Array.prototype.includes = function(searchElement /*, fromIndex*/ ) {
'use strict';
var O = Object(this);
var len = parseInt(O.length) || 0;
if (len === 0) {
return false;
}
var n = parseInt(arguments[1]) || 0;
var k;
if (n >= 0) {
k = n;
} else {
k = len + n;
if (k < 0) {k = 0;}
}
var currentElement;
while (k < len) {
currentElement = O[k];
if (searchElement === currentElement ||
(searchElement !== searchElement && currentElement !== currentElement)) { // NaN !== NaN
return true;
}
k++;
}
return false;
};
}
实现介绍:
- 首先判断该函数是否存在,对于不存在的情况我们定义了一个自己的function函数
- 将调用的对象this保存到变量0中,并将length保存在变量len中。
- 判断是否具有两个参数,如果参数2存在(起始位置参数)则将其保存在k中,对于负数我们从尾部开始计算(逆向)。
进入循环判定,其中这里最关键的是对于对象的比较,为了实现NaN的比较我们加入了一段新的判断代码
searchElement !== searchElement && currentElement !== currentElement
对于NaN,我们知道NaN !== NaN 所有我们的判断中对于自身进行了判断,如果自己不等于自己 则肯定为NaN。
加入新的判定后,会对于实现的效率有所降低。以下我们选择的是100万次的比较,对于正常的使用,函数的性能不会影响太大。
var indexOfTime=function(){
var begin=new Date().getTime();
for(var i=0;i<1000000;i++) {
[1,2,3].indexOf(4)
}
console.log((new Date().getTime())-begin);
}
var includesTime=function(){
var begin=new Date().getTime();
for(var i=0;i<1000000;i++) {
[1,2,3].includes(4)
}
console.log((new Date().getTime())-begin);
}
indexOfTime()
VM7330:6 34
indexOfTime()
VM7330:6 20
includesTime()
VM7396:6 167
includesTime()
VM7396:6 190
总结
Array.prototype.includes在实现上并非扩展了原有的indexOf 因为并未返回检索位置信息,只是单纯的返回一个查询的bool值。但是增加了对于NaN的支持,使得查询更加的全面。原文放置在个人Blog上欢迎大家访问jsmean.com,后期我也会增加一些新的内容,欢迎大家一起学习讨论。