JavaScript数组(ES6)
JavaScript数组一篇中介绍了ES6之前的数组方法。本篇介绍一下ES6里新增的数组方法。
- find,findIndex,inclueds
- fill,copyWithin
- keys,values,entries
- 静态方法(from,of)
find,findIndex,inclueds
find用于找元素,返回第一个满足条件的元素,找不到就返回undefined。函数声明:[].find( function(value, index, array) { … }, [thisArg] );
。参照MDN
第一个参数是回调函数,它支持3个参数,第1个是遍历的数组内容,第2个是对应索引,第3个是数组自身。第二个参数thisArg可选,可用于以改变回调函数里面的this指针
var count = [1, 5, 10, 15].find(function(value, index, arr) {
return value > 9;
});
console.log(count); //10
findIndex用于找元素,返回第一个满足条件的元素的位置,找不到就返回-1。函数声明:[].findIndex( function(value, index, array) { … }, [thisArg] );
,和上面find一样,不赘述。参照MDN
var idx = [1, 5, 10, 15].findIndex(function(value, index, arr) {
return value > 9;
});
console.log(idx); //2
这两个方法都可以发现NaN,弥补了之前indexOf方法的不足。indexOf方法无法识别数组的NaN元素,但findIndex方法可以借助Object.is方法做到:
var idx1 = [NaN].indexOf(NaN);
console.log(idx1); //-1
var idx2 = [NaN].findIndex(y => Object.is(NaN, y));
console.log(idx2); //0
includes用于找元素,找到返回true,找不到返回false。函数声明:[].includes(el, [start]);
。参照MDN
第一个参数是查找的元素。第二个参数可选,表示开始查找的位置,不指定的话默认为0,指定为负数,表示倒着数。
[1, 2, 3].includes(2); // true
[1, 2, 3].includes(4); // false
[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true
[1, 2, NaN].includes(NaN); // true
以前要看数组中是否包含某元素用indexOf:if (arr.indexOf(el) !== -1) { … }
。除了感觉有点不自然外,也无法判断是否包含NaN。现在用includes就没这些问题了。
fill,copyWithin
fill用于填充当前数组,返回填充后的数组。函数声明:[].fill(value, [start, [end]]);
。参照MDN
第一个参数是填充的元素,后两个参数可选,start是起始填充位置,不指定的话默认为0。end是填充到哪个位置之前结束,不指定的话默认到数组尾。位置可以指定负数,表示倒着数。
var arr = [1, 2, 3];
console.log(arr.fill(4)); // [4, 4, 4]
console.log(arr.fill(4, 1)); // [1, 4, 4]
console.log(arr.fill(4, 1, 2)); // [1, 4, 3]
console.log(arr.fill(4, -3, -2)); // [4, 2, 3]
用上面第一行例子,即单个参数,来初始化数组非常方便,数组中原有元素将全部被抹去。
copyWithin和fill很像,它用于将数组指定位置的元素复制到其他位置(会覆盖原来该位置的元素),最后返回修改后的数组。函数声明:[].copyWithin(target, [start, [end]]);
。参照MDN
第一个参数和fill有区别,是从该位置开始替换元素。后两个参数参照fill,不赘述
var arr = ['a', 'b', 'c', 'd', 'e', 'f'];
console.log(arr.copyWithin(0, 3)); // ['d', 'e', 'f', 'd', 'e', 'f']
表示将从index为3开始直到数组结束的成员(即def)读取出来,替换从0号位开始的元素(即覆盖了abc)。
再看一个负数的例子:
var arr1 = [1, 2, 3, 4, 5];
console.log(arr1.copyWithin(-2, -3, -1)); // [1, 2, 3, 3, 4]
从倒数3位开始直到倒数1位(即34)读取出来,替换倒数2位(即覆盖了45)
keys,values,entries
这3个方法都用于遍历数组。都返回一个遍历器对象,可以用for…of循环进行遍历。区别是keys是对key的遍历,values是value的遍历,entries是对key-value的遍历。
函数声明都非常简单,一个参数都没有,分别是:[].keys();
,[].values();
,[].entries();
。参照MDN
for (let index of ['a', 'b'].keys()) {
console.log(index);
}
// 0
// 1
for (let elem of ['a', 'b'].values()) {
console.log(elem);
}
// 'a'
// 'b'
for (let [index, elem] of ['a', 'b'].entries()) {
console.log(index, elem);
}
// 0 "a"
// 1 "b"
因为返回的是遍历器对象,因此除了for…of循环外,也可以手动调用遍历器对象的next方法来遍历:
var arr = ['a', 'b', 'c'];
var eArr = arr.entries();
console.log(eArr.next().value); // [0, 'a']
console.log(eArr.next().value); // [1, 'b']
console.log(eArr.next().value); // [2, 'c']
静态方法(from,of)
JavaScript数组一篇中介绍了ES6之前的数组方法,包括本篇上面所有Array的方法的函数声明都用了“[].方法名”的形式,等价于“Array.prototype.方法”,表示它们都是Array的实例方法。
但form和of的函数声明用了“Array.方法名”的形式,表示它们是Array的静态方法。(关于JS静态可以参照这里)
from用于将类数组对象转为真正的数组。函数声明:Array.from(arrayLike, [mapFn, [thisArg]]);
。参照MDN
第一个参数自然就是类数组对象。第二个参数作用类似于map,还可以为map指定this。有关类数组对象和map方法请参照JavaScript数组,不赘述。
现在用ES6的from方法来重写JavaScript数组一篇中的类数组对象中的例子:
处理arguments对象:
//ES5处理arguments对象:
var args = [].slice.call(arguments);
//ES6用from
var args = Array.from(arguments);
处理HTMLCollection对象:
//ES5用forEach遍历页面所有div,输入className
var divs = document.getElementsByTagName("div");
Array.prototype.forEach.call(divs, function(div) {
console.log("该div类名是:" + (div.className || "空"));
});
// ES6用from
Array.from(divs).forEach(function (div) {
console.log("该div类名是:" + (div.className || "空"));
});
处理字面量对象:
//ES5
var arrayLike = { 0: "a", 1: "b", 2: "c", length: 3 };
var result = Array.prototype.map.call(arrayLike, function(s) {
return s.toUpperCase();
});
console.log(result); //["A", "B", "C"]
//ES6
var result = Array.from(arrayLike, s => s.toUpperCase());
console.log(result); //["A", "B", "C"]
上面from用了第二个参数,该语句等价于Array.from(arrayLike).map(s => s.toUpperCase());
处理字符串:
//ES5
var result = Array.prototype.map.call("abc", function(s) {
return s.toUpperCase();
});
console.log(result); //["A", "B", "C"]
//ES6
var result = Array.from("abc", s => s.toUpperCase());
console.log(result); //["A", "B", "C"]
of作用和from类似,用于将一组值,转换为数组。函数声明:Array.of(el0, [el1, … , elN]);
。参照MDN
和from一样, 同样是Array的静态方法,你无法用数组对象调用of方法。
console.log(Array.of(1,2,3)); // [1, 2, 3]
你可能会很疑惑,直接var arr = new Array(1,2,3);
不就行了,要of方法有什么用?如果只有1个参数就有区别了:
//只有1个参数的普通构造函数
var arr1 = Array(3);
console.log(arr1); // [, , ,]
//ES6用of就和上面有区别了
var arr2 = Array.of(3);
console.log(arr2); // [3]
可以看出用of的话,可以完全替代构造函数,避免了单个参数导致的非常微妙的区别。它总是能返回一个数组,如果没有参数,就返回空数组[]