ES6类型扩展-数组扩展

静态方法

ES6之前,创建数组的方式主要由两种:一种是调用Array构造函数,另一种是数组字面量。ES6新增了Array.of()和Array.from()两个方法也用于创建数组。

Array.of()

ES6添加这些新方法,是为了帮助开发者规避通过Array构造函数创建数组是的怪异行为。

// 示例1
let arr =new Array(3)
console.log(arr.length) // 3
console.log(arr[0]) // undefined

// 示例2
let arr =new Array('3')
console.log(arr.length) // 1
console.log(arr[0]) // '3'

// 示例3
let arr =new Array(3,2,1)
console.log(arr.length) // 3
console.log(arr[0]) // 3

如果Array构造函数传入一个数值型的值,则数组的length属性会被设置为该值。如果传入多个值,则这些值都会成为数组的元素。很多时候可能并不会去检测元素的个数,这就无形中埋下了风险。

ES6通过引入Array.of()方法来解决这个问题。Array.of()与Array构造函数的工作机制类似,只是不存在单一数值型参数值的特例,无论有多少参数,无论参数是什么类型的,Array.of()方法总会创建一个包含所有参数的数组

// 示例1
let arr =Array.of(3)
console.log(arr.length) // 1
console.log(arr[0]) // 3

// 示例2
let arr =Array.of('3')
console.log(arr.length) // 1
console.log(arr[0]) // '3'

大多数时候,可以用数组字面量来创建数组,但如果需要给一个函数传入Array的构造函数,更好地方法时传入Array.of()来确保行为一致

Array.form()

JS不支持直接将类数组对象转换成真实数组,于是ES6添加了一个语义清晰、语法简洁的新方法Array.from()来将对象转化为数组

function foo() {
  return Array.from(arguments)
}

console.log(foo(1,2,3)); // [1, 2, 3]

arguments是一个类数组对象,Array.from()方法调用会基于arguments对象中的元素创建一个新数组,包含arguments对象中同位置的相同值

映射转换

如果想要进一步转化数组,可以提供一个映射函数作为Array.from()的第二个参数,这个函数用来将类数组对象中的每一个值转换成其他形式,最后将这些结果储存在结果数组的相应索引中

function foo() {
  return Array.from(arguments, v => v + 1)
}

console.log(foo(1,2,3)); // [2, 3, 4]

如果用映射函数处理对象,也可以给Array.from()方法传入第三个参数来表示映射函数的this值

let obj = {
  num: 1,
  add(v) {
    return this.num + v;
  }
}

function foo() {
  return Array.from(arguments, obj.add, obj)
}

console.log(foo(1,2,3)); // [2, 3, 4]

Array.from()方法可以处理类数组对象和可迭代对象,也就是说该方法能够将所有含有Symbol.iterator属性的对象转换为数组

let set = new Set([1,2,3]);
let ret = Array.from(set, v => v+ 1);
console.log(ret) // [2, 3, 4]

Set集合是一个可迭代对象,因此可以直接将它传入Array.from()来转换成数组

实例方法

ES6为数组的实例添加了几个新方法

includes()

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

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

该方法可以接收可选的第二个参数,表示搜索的起始位置,默认值0。如果第二个参数是负数,则表示倒数位置,如果这个负数的绝对值大于数组的长度,则会重置为0。

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

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

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

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

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

[NaN].indexOf(NaN) !== -1; // false
[NaN].includes(NaN); // true

find()和findIndex()

由于没有内建的数组搜索方法,ES5正式添加了indexOf()和lastIndexOf()两个方法,可以用它们查找元素在数组中的索引,找不到就返回-1,但这两种方法仍有局限之处,比如我想在一系列数字中查找第一个偶数,则必须自己编写代码来实现。于是ES6引入了find()方法和findIndex()方法来解决这个问题

find()方法和findIndex()方法都接收两个参数:第一个参数是一个回调函数;第二个参数是可选的,表示回调函数的this值。函数有三个参数,分别表示数组中的某个元素、该元素的索引、原始数组。如果给定的值满足回调函数的要求,这两个方法会停止搜索数组剩余的部分

二者间唯一的区别是,find()方法返回查找到的值,findIndex()方法返回查找到的值的索引

// 示例1
let arr = [1,2,3,4,5];
let ret = arr.find((item, index, array) => item > 3);
let ret2 = arr.findIndex((item, index, array) => item > 3);
console.log(ret,ret2) // 4 3

// 示例2
let arr = [1,2,3,4,5];
let ret = arr.find((item, index, array) => index > 3);
let ret2 = arr.findIndex((item, index, array) => index > 3);
console.log(ret,ret2) // 5 4

示例1表示查找数组中第一个成员值大于3的元素和这个元素的索引
示例2表示查找数组中第一个索引值大于3的元素和这个元素的索引

如果要在数组中根据某个条件查找匹配的元素,那么find()方法和findIndex()方法可以很好地完成任务;如果只想查找与某个值匹配的元素,则indexOf()方法和lastIndexOf()方法是更好的选择

fill()

fill()方法可以用指定的值填充数组元素。该方法接收接收三个参数:第一个表示要填充的值;第二个参数可选,表示开始填充的索引位置;第三个参数也是可选的,表示结束填充的索引位置(不包含结束位置)。

如果省略开始索引和结束索引,则默认填充整个数组。如果开始索引或结束索引为负值,那么这些值会与数组的length属性相加来作为最终位置

// 示例1
let arr = [1,2,3,4,5];
arr.fill(1); 
console.log(arr); // [1, 1, 1, 1, 1]

// 示例2
let arr = [1,2,3,4,5];
arr.fill(1,2); 
console.log(arr); // [1, 2, 1, 1, 1]

// 示例3
let arr = [1,2,3,4,5];
arr.fill(1,2,4); 
console.log(arr); // [1, 2, 1, 1, 5]

示例1表示用数字1填充整个数组
示例2表示用数字1填充从索引位置2到索引结束位置的数组
示例3表示用数字1填充从索引位置2到索引位置4的数组

注意: 该方法会改变原始数组

copyWithin()

copyWithin()方法可以从数组中复制元素的值。该方法接收三个参数:第一个表示开始填充的索引位置;第二个参数可选,表示开始复制值的索引位置;第三个参数也是可选的,表示结束复制值的索引位置(不包含该位置的值)

如果省略开始复制值的索引位置和结束复制值的索引位置,则默认复制整个数组元素。该方法所有参数都接受负数值,并且会自动与数组长度相加来作为最终使用的索引

// 示例1
let arr = [1,2,3,4,5];
arr.copyWithin(1); 
console.log(arr); // [1, 1, 2, 3, 4]

// 示例2
let arr = [1,2,3,4,5];
arr.copyWithin(1,2); 
console.log(arr); // [1, 3, 4, 5, 5]

// 示例3
let arr = [1,2,3,4,5];
arr.copyWithin(1,2,4); 
console.log(arr); // [1, 3, 4, 4, 5]

第一个示例表示从索引1的位置开始填充,由于没有开始复制位置和结束复制位置,所以会复制整个数组,即1,2,3,4,5

第二个示例表示从索引1的位置开始填充,从索引2的位置开始复制,一直复制到结束,即复制了3,4,5。

第二个示例表示从索引1的位置开始填充,从索引2的位置开始复制,复制到索引4结束,即复制了3,4。

注意: 该方法会改变原始数组

posted @ 2021-09-29 12:56  wmui  阅读(35)  评论(0编辑  收藏  举报