5.1 静态方法我敢和你打赌,ES5中数组提供的五花八门的方法就足以令你应接不暇了,你甚至可能都没听说过像[].reduce这类的方法。好吧,ES6又加大了你记忆曲线的弧度——它提供了更多方便使用方法以及可能会成为冷门的方法。所以我强烈建议你在看这篇文章之前先去下定决心把文章提到的以及ES5中数组的方法一一付诸实践。
Array.from(obj[,cb[,context]])
Array.from方法用于将类数组对象(最基本的特征只需要有length属性)和可遍历对象转为真正的数组。
DOM集合和arguments是最经典类数组对象,在以前我们大概会使用下面的方式将其转化为一个数组:
var arr = [].slice.apply(arguments);
在ES6中,我们可以使用Array.from方法:
var arr = Array.from(arguments);
只要是部署了Iterator接口的对象,即可遍历的对象,Array.from都可以将其转化为一个真正的数组。比如字符串和Set集合。下面的代码会将一个字符串转为以单个字符为元素的数组:
let str = 'hello world';
let arr = Array.from(str);
// 等价于
let arr = str.split('')
有的时候我们的字符串中会出现四字节字符,会导致str.length出现异常行为,可以将字符串转化为数组,在获取数组length的值。
我们可以配合Set集合默认去除重复元素的特性来实现数组去重:
let arr = ['a','b','c','d','a','e','c']; // 需要去重的数组
let set = new Set(arr); // 创建一个Set集合,集合会默认去除重复的元素
newArr = Array.from(set); // 将Set集合转化为一个数组
console.log(Array.isArray(newArr)); //=> true
console.log(newArr); // ['a','b','c','d','e']
还有一个极端的例子
Array.from({length:3}); // =>[undefined, undefined, undefined]
另外不得不提的是括展元素符...
,它也可以将部署了遍历器接口的变量转化为数组,它和Array.from
的区别在于,它无法转化那些只有length
属性的类似数组的对象。
let newArr = [...set]
Array.from方法还可以接受第二个参数,类似于[].map
方法的回调函数,它会对将要返回的数组元素进行加工:
Array.from(new Set(['a','b','a']), item=>item+'@'); //=> ['a@', 'b@']
也可以在使用Array.from时传入你想指定的上下文this作为第三个参数。
如果Array.from方法接收到一个正经的数组,它会什么也不做,原封不动的返回,但有一种“不正经”的数组——空位数组:[1,5,,6]
,这往往是由于编码的不小心失误产生的。Array.from在处理这样的数组时,不像foreach()\filter\every\some\map那样自动跳过空位,而是默认为它填充undefined。
数组中空位不等于undefined,一个位置的值是undefined表明其仍然是有值的
另外补充一句,join方法会将空位视为undefined,而将undefined和null视为空字符串。
Array.of(...args)
Array.of用于将一组值转化为数组,其作用与Array构造器类似,但区别在于Array.of不会出现Array构造器那样怪异的行为:
Array.of(3) // =>[3];
new Array(3) // =>[,,]
5.2 实例方法
Array.prototype.find/findIndex(cb[, context])
实例方法find和findIndex用来在数组元素中寻找符合条件的第一个元素,前者返回这个元素本身,而后者返回这个元素在数组中的索引。它们接受一个回调函数作为参数,我们在里面的return语句中设定需要满足的条件。和forEach相同,这个回调函数会被注入三个参数:元素本身、元素的索引和数组本身。下面是一个例子:
// 寻找数组中的数组
let arr = [1,-2,3,4,5,6,7];
let negative = arr.find(item=>item<0); //-2
let negativeIndex = arr.findIndex(item=>item<0); //1
如果未找到符合条件的元素,find方法返回undefined,而findIndex方法返回-1.
我们知道,在ES5中,数组实例的indexOf方法无法发现值为NaN的元素:
// ES5中的indexOf方法没有办法找到数组中的NaN,因为NaN!==NaN
let arr = [1,2,3,4,NaN];
console.log(arr.indexOf(NaN));// -1
在ES6中,我们可以使用find方法自定义条件来实现这个功能:
let foo = arr.find((item) => {
return item!==item;
});
此外,还可以传入你想指定的上下文作为第二个参数。
Array.prototype.fill(value, [start = 0[, end = arr.length]])
这个方法可以用来填充数组,它适合填充空数组:
let arr = new Array(3);
arr.fill(6);
arr// => [6,6,6]
let array = [1,2,3,4,5,6];
array.fill('hello',2,3);
console.log(array); //[1, 2, "hello", 4, 5, 6]
注意,这个方法会影响原来的数组,将选中的已有元素抹去
Array.prototype.copyWithin(target [, start = 0[, end = arr.length]])
let array = [1,2,3,4,5,6];
array.copyWithin(0,3);
console.log(array); //[4, 5, 6, 4, 5, 6]
这个方法相对较难理解,它的第一个参数是指从哪里开始进行替换,上面的例子中我们选择了从索引为0的地方开始替换。第二个参数是从哪里开始读取替换成的元素,我们选择了从第4个元素(索引3)开始读取,第三个参数表示读取到哪里,我们没有写,默认就是到数组的末尾。好,这样我们就获得了我们将要进行替换的元素:4,5,6。将要从第1个元素(索引1)开始替换,所以最后的结果是[4, 5, 6, 4, 5, 6]。
注意:一共有几个元素被替换由读取的元素的个数决定,比如上面的例子,我们一共读取了4、5、6三个元素,所以从0号元素开始向后数3个元素,即1、2、3被替换了。这个方法会印象原来的数组
start和end可以是负数,-1就表示倒数第一个数。
5.3 返回遍历器的方法ES6提供了entries()\keys()\values()三个方法用来遍历数组,它们都返回一个遍历器对象,可以使用for...of循环进行遍历。
let arr = [1,2,3,4,5,6];
for(let index of arr.keys()){
console.log(index);
}// =>0 1 2 3 4 5
console.log('******************');
for(let value of arr.values()){
console.log(value)
} // 1 2 3 4 5 6 chrome5.7目前不支持该方法
console.log('******************');
for(let entry of arr.entries()){
console.log(entry);
} // [0,1] [1,2] [2,3] [3,4] [4,5] [5,6]
如果不使用for... ...of循环,可以手动调用遍历器对象的next方法进行遍历:
let entries = arr.entries();
console.log(entries.next()); //{value: [0,1], done: false}
console.log(entries.next().value); // [1,2]