JavaScript < ES5、ES6、ES7、… >ECMAScript 6

ES6(十) 数组扩展

2019-01-24  本文已影响28人  CodeMT

前面的话


  数组是一种基础的JS对象,随着时间推进,JS中的其他部分一直在演进,而直到ES5标准才为数组对象引入一些新方法来简化使用。ES6标准继续改进数组,添加了很多新功能。本文将详细介绍ES6数组扩展

静态方法

  在ES6以前,创建数组的方式主要有两种,一种是调用Array构造函数,另一种是用数组字面量语法,这两种方法均需列举数组中的元素,功能非常受限。如果想将一个类数组对象(具有数值型索引和length属性的对象)转换为数组,可选的方法也十分有限,经常需要编写额外的代码。为了进一步简化JS数组的创建过程,ES6新增了Array.of()Array.from()两个方法

【Array.of()】

ES6之所以向JS添加新的创建方法,是要帮助开发者们规避通过Array构造函数创建数组时的怪异行为

let items =new Array(2);
console.log(items.length); // 2
console.log(items[0]);// undefined
console.log(items[1]);// undefined
items =newArray("2");
console.log(items.length); // 1
console.log(items[0]);// "2"
items =new Array(1, 2);
console.log(items.length); // 2
console.log(items[0]);// 1
console.log(items[1]);// 2
items =new Array(3, "2");
console.log(items.length); // 2
console.log(items[0]);// 3
console.log(items[1]);// "2"
let items = Array.of(1, 2);
console.log(items.length); // 2
console.log(items[0]);// 1
console.log(items[1]);// 2
items = Array.of(2);
console.log(items.length); // 1
console.log(items[0]);// 2
items = Array.of("2");
console.log(items.length); // 1console.log(items[0]);// "2"
function createArray(arrayCreator, value) {  
  return arrayCreator(value);
}
let items = createArray(Array.of, value);

[注意] Array.of()方法不通过Symbol.species属性确定返回值的类型,它使用当前构造函数(也就是of()方法中的this值)来确定正确的返回数据的类型

【Array.from()】

   JS不支持直接将非数组对象转换为真实数组,arguments就是一种类数组对象,如果要把它当作数组使用则必须先转换该对象的类型。在ES5中,可能需要编写如下函数来把类数组对象转换为数组

function makeArray(arrayLike) { 
  var result = [];   
  for(vari = 0, len = arrayLike.length; i < len; i++) {
    result.push(arrayLike[i]);
  }   
  return result;
}
function doSomething() {   
  var args = makeArray(arguments);    // 使用 args
}
function makeArray(arrayLike) { 
  return Array.prototype.slice.call(arrayLike);
}
function doSomething() { 
  var args = makeArray(arguments);    // 使用 args
}
function doSomething() {   
  var args = Array.from(arguments);    // 使用 args 
}

[注意] Array.from()方法也是通过this来确定返回数组的类型的

映射转换

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

function translate() {  
  return Array.from(arguments, (value) => value + 1);
}
let numbers = translate(1, 2, 3);
console.log(numbers); // 2,3,4
let helper ={
  diff: 1,
  add(value) {    
    return value +this.diff;
}
};
function translate() {    
  return Array.from(arguments, helper.add, helper);
}
let numbers = translate(1, 2, 3);
console.log(numbers); // 2,3,4
let numbers = {   
  *[Symbol.iterator]() {
    yield 1;
    yield 2;
    yield 3;
  }
};
let numbers2 = Array.from(numbers, (value) => value + 1);
console.log(numbers2); // 2,3,4

[注意]如果一个对象既是类数组又是可迭代的,那么Array.from()方法会根据迭代器来决定转换哪个值

实例方法

ES6延续了ES5的一贯风格,也为数组添加了几个新的方法:includes()方法返回一个布尔值,表示数组是否包含给定的值;find()方法和findIndex()方法可以协助开发者在数组中查找任意值;fill()方法和copyWithin()方法的灵感则来自于定型数组的使用过程,定型数组也是ES6中的新特性,是一种只包含数字的数组

【includes()】

[1, 2, 3].includes(2)// true
[1, 2, 3].includes(4)// false
[1, 2, NaN].includes(NaN)// true
[1, 2, 3].includes(3, 3);// false
[1, 2, 3].includes(3, -1);// true
if(arr.indexOf(el) !== -1) { 
 // ...
}
[NaN].indexOf(NaN)// -1
[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

1、Map结构的has方法,是用来查找键名的,比如Map.prototype.has(key)WeakMap.prototype.has(key)Reflect.has(target,propertyKey)

2、Set结构的has方法,是用来查找值的,比如Set.prototype.has(value)WeakSet.prototype.has(value)

【find()和findIndex()】

  由于没有内建的数组搜索方法,因此ES5正式添加了indexOf()lastIndexOf()两个方法,可以用它们在数组中查找特定的值。虽然这是一个巨大的进步,但这两种方法仍有局限之处,即每次只能查找一个值,如果想在系列数字中查找第一个偶数,则必须自己编写代码来实现。于是ES6引入了find()方法和findIndex()方法来解决这个问题

let numbers = [25, 30, 35, 40, 45];
console.log(numbers.find(n => n > 33));// 35
console.log(numbers.findIndex(n => n > 33));// 2

【fill()】

let numbers = [1, 2, 3, 4];
numbers.fill(1);
console.log(numbers.toString()); // 1,1,1,1
let numbers = [1, 2, 3, 4];
numbers.fill(1, 2);
console.log(numbers.toString()); // 1,2,1,1
numbers.fill(0, 1, 3);
console.log(numbers.toString()); // 1,0,0,1

[注意]如果开始索引或结束索引为负值,那么这些值会与数组的length属性相加来作为最终位置。例如,如果开始位置为-1,那么索引的值实际为array.length-1array为调用fill()方法的数组

【copyWithin()】

  copyWithin()方法与fill()方法相似,其也可以同时改变数组中的多个元素。fill()方法是将数组元素赋值为一个指定的值,而copyWithin()方法则是从数组中复制元素的值。调用copyWithin()方法时需要传入两个参数:一个是该方法开始填充值的索引位置,另一个是开始复制值的索引位置

let numbers = [1, 2, 3, 4];
// 从索引 2 的位置开始粘贴
// 从数组索引 0 的位置开始复制数据numbers.copyWithin(2, 0);
console.log(numbers.toString()); // 1,2,1,2
let numbers = [1, 2, 3, 4];
// 从索引 2 的位置开始粘贴
// 从数组索引 0 的位置开始复制数据
// 在遇到索引 1 时停止复制
numbers.copyWithin(2, 0, 1);
console.log(numbers.toString()); // 1,2,1,4

[注意]正如fill()方法一样,copyWithin()方法的所有参数都接受负数值,并且会自动与数组长度相加来作为最终使用的索引

上一篇 下一篇

猜你喜欢

热点阅读