数组实例的 方法

68 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第16天,点击查看活动详情

数组实例的 fill()

`fill` 方法使用给定值,填充一个数组。

['a', 'b', 'c'].fill(7)
// [7, 7, 7]

new Array(3).fill(7)
// [7, 7, 7]


上面代码表明,`fill` 方法用于空数组的初始化非常方便。数组中已有的元素,会被全部抹去。

`fill` 方法还可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置。

['a', 'b', 'c'].fill(7, 1, 2)
// ['a', 7, 'c']


上面代码表示,`fill` 方法从 1 号位开始,向原数组填充 7,到 2 号位之前结束。

注意:如果填充的类型为对象,那么被赋值的是同一个内存地址的对象,而不是深拷贝对象。

let arr = new Array(3).fill({name: "Mike"});
arr[0].name = "Ben";
arr
// [{name: "Ben"}, {name: "Ben"}, {name: "Ben"}]

let arr = new Array(3).fill([]);
arr[0].push(5);
arr
// [[5], [5], [5]]

数组实例的 entries(),keys() 和 values()

ES6 提供三个新的方法 —— `entries()``keys()` 和 `values()` —— 用于遍历数组。它们都返回一个遍历器对象(详见 《Iterator》  一章),可以用 for...of 循环进行遍历,唯一的区别是 `keys()` 是对键名的遍历、`values()` 是对键值的遍历,`entries()` 是对键值对的遍历。


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` 方法,进行遍历。

let letter = ['a', 'b', 'c'];
let entries = letter.entries();
console.log(entries.next().value); // [0, 'a']
console.log(entries.next().value); // [1, 'b']
console.log(entries.next().value); // [2, 'c']

数组实例的 includes()

`Array.prototype.includes` 方法返回一个布尔值,表示某个数组是否包含给定的值,与字符串的 `includes` 方法类似。ES2016 引入了该方法。

[1, 2, 3].includes(2)     // true
[1, 2, 3].includes(4)     // false
[1, 2, NaN].includes(NaN) // true


该方法的第二个参数表示搜索的起始位置,默认为 0。如果第二个参数为负数,则表示倒数的位置,如果这时它大于数组长度(比如第二个参数为 -4,但数组长度为 3),则会重置为从 0 开始。

[1, 2, 3].includes(3, 3);  // false
[1, 2, 3].includes(3, -1); // true


没有该方法之前,我们通常使用数组的 `indexOf` 方法,检查是否包含某个值。

if (arr.indexOf(el) !== -1) {
  // ...
}


`indexOf` 方法有两个缺点,一是不够语义化,它的含义是找到参数值的第一个出现位置,所以要去比较是否不等于 -1,表达起来不够直观。二是,它内部使用严格相等运算符(===)进行判断,这会导致对 NaN 的误判。

[NaN].indexOf(NaN)
// -1


`includes` 使用的是不一样的判断算法,就没有这个问题。

[NaN].includes(NaN)
// true


下面代码用来检查当前环境是否支持该方法,如果不支持,部署一个简易的替代版本。

const contains = (() =>
  Array.prototype.includes
    ? (arr, value) => arr.includes(value)
    : (arr, value) => arr.some(el => el === value)
)();
contains(['foo', 'bar'], 'baz'); // => false


另外,Map 和 Set 数据结构有一个 `has` 方法,需要注意与 `includes` 区分。

-   Map 结构的 `has` 方法,是用来查找键名的,比如 Map.prototype.has(key)、WeakMap.prototype.has(key)、Reflect.has(target, propertyKey)。
-   Set 结构的 `has` 方法,是用来查找值的,比如 Set.prototype.has(value)、WeakSet.prototype.has(value)。