ES6新增API(Array篇(一))

新增的静态函数

  1. Array.of
    函数类型:
    //接收任意数量、任意类型的参数,返回这些参数按照传入顺序组成的数组 (...args?:any[])=>any[];

    【ES6新增API(Array篇(一))】Array.of用于创建一个具有可变数量参数的新的数组实例。它和通过Array构造函数创建数组的不同之处在于,当使用new Array的方式创建数组时,如果只传入了一个整数参数a,则会创建一个长度为a的数组,每个元素都是空位(指empty,而不是undefined),而Array.of则会创建返回[ a ]
    console.log(Array(3)); //[ <3 empty items> ] console.log(Array.of(3)); // [ 3 ]

    当我们需要根据传入的参数来创建数组时,如果使用的Array构造函数,而且没有特殊处理参数只有一个整数的情况,就会出现意料之外的情况。这种并非逻辑上的、细节性的问题,在修复时,往往我们也是最难以意识到的一类问题。
  2. Array.from
    函数类型:
    /** * @author: forceddd * @desc: 根据传入的一个伪数组或可迭代对象创建一个新的、浅拷贝的数组实例 * @param {ArrayLike|Iterable} arrayLike 传入的数据源 * @param {MapFn} mapFn 可选的映射函数,与Array.map用途相同 * @param {any} thisArg 可选的this对象,映射函数mapFn中的this会指向该参数 * @return {any[]} 新创建的数组 */ (arrayLike:ArrayLike | Iterable, mapFn?: MapFn, thisArg?: any) => any[]; /** * @author: forceddd * @desc: 映射回调 * @param {any} value 数组中的元素 * @param {number} index 元素的在数组中的下标 * @return {any} 映射返回的值 */ type MapFn = (value: any, index: number) => any;

    Array.from是根据传入的一个伪数组或可迭代对象创建一个新的、浅拷贝的数组实例。
    Array.of不同,Array.of是直接将参数作为返回值数组中的元素,而Array.from会根据传入的参数来产生返回值数组:
    当传入伪数组时,伪数组的length会作为返回值数组的length,伪数组的元素会作为返回值数组的元素。
    //传入了一个伪数组 console.log(Array.from({ 0: '第一项元素', length: 2 })); //[ '第一项元素', undefined ] // tag属性不能转换成数组下标,被过滤掉了 console.log(Array.from({ 0: '第一项元素', length: 2, tag: '一个字符串key' })); //[ '第一项元素', undefined ] //传入的是一个普通对象,既不是伪数组,也不是一个iterable对象,返回一个空数组 console.log(Array.from({ 0: '第一项元素', tag: '一个字符串key' })); //[]

    当传入一个iterable对象参数时,比如ArraySet等,会对参数进行迭代,并将迭代得到的值作为返回值数组中的元素。
    console.log(Array.from([1, , 3])); //[ 1, undefined, 3 ] console.log(Array.from(new Set([1, , 3]))); //[ 1, undefined, 3 ] //传入了一个映射函数 console.log(Array.from([1, 2, 3], (item) => 2 * item)); //[ 2, 4, 6 ] const obj = { value: 0, //自定义[Symbol.iterator] ,是该对象成为iterable对象,执行得到的迭代器是它自身 [Symbol.iterator]() { return this; }, //value > 3 后,设置迭代状态为true,结束迭代 next() { this.value++; return { value: this.value, done: this.value > 3, }; }, }; //传入一个自定义的iterable console.log(Array.from(obj)); //[ 1, 2, 3 ]

    需要注意的是,Array.from不会产生空位(empty),如果传入的参数中,该位置的元素是空位(empty),会使用undefined作为结果。
    当我们需要将一个伪数组转为真正的数组,以便使用数组的map等方法时——比如进行dom操作,相较于使用[].slice.call(arrayLike)来说(这种方法有可能产生空位(empty)元素),使用Array.from无疑是一个更优雅也更简洁的方式。
  3. 为什么要避免数组中的空位元素?
    在处理数组的函数中,不同的函数对待空位元素的方式是不同的,有些函数会忽略空位元素,比如map函数,而有些则不会忽略,比如Array.from,这就很有可能会产生一些莫名其妙的问题。
    假如我们需要通过变量count统计一个数组的length,这可以让我们很明显的看到空位元素的问题所在。
    当存在空位元素时:
    const empty = [1, , 3]; let count1 = 0; let count2 = 0; empty.map(() => count1++); Array.from(empty, () => count2++); //由于map函数忽略了空位元素,所以传入的回调只执行了两次,count1的值为2 console.log({ count1, count2 }); //{ count1: 2, count2: 3 }

    当不存在空位元素时:
    const normal = [1, undefined, 3]; let count1 = 0; let count2 = 0; normal.map(() => count1++); normal.forEach(() => count2++); console.log({ count1, count2 }); //{ count1: 3, count2: 3 }

    推荐阅读