ES6新增API:Array篇(二)

新增的原型方法

  1. Array.prototype.copyWithin

    函数类型:

    /**
    * @author: forceddd
    * @desc:  将数组中的,从start位置开始至end位置(不包含end处的元素)结束的元素,进行浅复制,并从target处开始覆盖该数组。最后将修改后的数组返回
    * @param {number} target 复制到数组的起始覆盖位置,默认值为0
    * @param {number} start 开始复制元素的位置,默认值为0
    * @param {number|undefined} end 结束复制元素的位置,默认值为数组长度
    * @return {any[]} 改变之后的数组
    */
    (target?: number, start?: number, end?: number | undefined)=> T[]

    copyWithin将数组中的,从start位置开始至end位置(包含end处的元素)结束的元素,进行浅复制,并从target处开始覆盖该数组。最后将修改后的数组返回。

    //不传入参数时,都使用默认值,相当于 [1, 2, 3].copyWithin(0,0,3)
    //首先复制了数组中的[ 0, 3 )的部分,即[1,2,3]
    //然后从数组的下标0处开始覆盖,覆盖之后得到[1, 2, 3]
    console.log([1, 2, 3].copyWithin()); //[ 1, 2, 3 ]
    //从数组的下标1处开始覆盖,复制的部分为[1, 2, 3],从原数组的下标1处开始覆盖,原数组只剩余两个位置,所以结果为[ 1, 1, 2 ]
    console.log([1, 2, 3].copyWithin(1)); //[ 1, 1, 2 ]

    有几点需要注意的是:

    第一,copyWithin会修改原数组,返回的是修改之后的原数组,而不是创建的一个新数组。

    const arr = [1, 2, 3];
    const res = arr.copyWithin(1, 0);
    
    console.log(arr === res, arr);//true [ 1, 1, 2 ]

    第二,当target>=arr.length时,不会发生复制行为,直接返回没有进行任何修改的原数组。

    const arr = [1, 2, 3];
    const res = arr.copyWithin(6, 2);
    //返回没有进行任何修改的原数组
    console.log(arr === res, arr); //true [ 1, 2, 3 ]

    第三,当targetstart或者end传入负数时,代表此时的从数组末尾开始计算,假如传入的值是-1,就代表倒数第一个元素的位置。

    const arr = [1, 2, 3];
    const res = arr.copyWithin(-2, 2);
    //从下标2开始复制得到的复制部分为 [ 3 ]
    //从-2,即倒数第二个元素开始覆盖,就得到了 [1, 3, 3 ]
    console.log(arr === res, arr); //true [ 1, 3, 3 ]
  2. Array.prototype.fill

    函数类型:

    /**
    * @author: forceddd
    * @desc: 将数组从start位置开始至end结束(不包括end)的部分都赋值为value
    * @param {any} value 用来给数组中元素赋值的值
    * @param {number} start 赋值的起始位置,默认为0
    * @param {number} end 赋值的结束位置,默认为数组的长度
    * @return {*} 返回值为赋值之后的原数组
    */
    (value?: any, start?: number, end?: number) => any[];

    fill 将数组从start位置开始至end结束(不包括end)的部分都赋值为value,然后将数组返回。

    console.log(Array(4).fill()); //[ undefined, undefined, undefined, undefined ]
    console.log(Array(4).fill(0)); //[ 0, 0, 0, 0 ]
    console.log(Array(4).fill(0, 1, 2)); //[ <1 empty item>, 0, <2 empty items> ]

    fillcopyWithin一样,返回的也是原数组,并且当start或者end负数时,也是和copyWithin相同的处理方式。

    除此之外,从代码中也可以看出,fill会产生空位元素,而且如果value值为对象,则赋值时使用的是对象的引用。换句话说:

    const v = [];
    const arr = Array(4).fill(v);
    console.log(arr[0] === arr[1]); //true
    arr[0].push(1);
    console.log(arr);//[ [ 1 ], [ 1 ], [ 1 ], [ 1 ] ]
  3. Array.prototype.find

    函数类型:

    /**
    * @author: forceddd
    * @desc:   找到数组中使得findFn返回值为true的第一个元素并将其返回
    * @param {FindFn} findFn 数组每一项上执行的函数
    * @param {any} thisArg 回调函数findFn中的this对象
    * @return {*}
    */
    (findFn: FindFn, thisArg?: any) => any;
    /**
    * @author: forceddd
    * @param {any} item 数组中的元素
    * @param {number} index 当前元素在数组中的下标
    * @param {any} arr 数组实例
    * @return {boolean} 
    */
    type FindFn = (item: any, index: number, arr: any[]) => boolean;

    find会返回数组中使得回调函数返回值为true第一个元素,如果没有这样的元素,会返回undefined

    console.log([1, 2, 3].find((v) => v >= 2));//2
    在ES6之前,使用 indexOf方法需要进行严格匹配( ===)才能判定元素是否存在,使用 some方法虽然可以自定义比对的回调函数,但是只能返回 boolean,而不能获得元素本身。

    需要注意的是,find中回调函数的执行次数是根据数组的下标决定的,下标 [ 0 , arr.length - 1 ] 的范围都会执行一次,它不关心当前元素的值,所以在当前元素是空位元素的时候,find中的回调函数会把元素值作为undefined执行一次,这和mapforEach等函数是不同的。

    [1, , 3, 4].find((v) => console.log(v)); //1 undefined 3 4
    [1, , 3, 4].map((v) => console.log(v)); //1 3 4

    另外,当find中的回调函数第一次执行时,它的执行次数 [ 0 , arr.length - 1 ] 就已经确定了,并且不会再改变。这也就意味着,假设我们要处理的数组arr长度为5,在回调函数执行的过程中,我们修改了arr,使其长度成为了10,或者我们删除了一个元素,使其长度变为4,回调函数都会执行5次。当元素被删除的情况下,回调函数在执行时访问不到该元素,会以undefined代替该元素继续执行。

    [1, 2, 3, 4].find((v, i, arr) => {
    //删除一个元素
    i === 0 && arr.pop();
    console.log({ v, i });
    }); 
    //{ v: 1, i: 0 }
    //{ v: 2, i: 1 }
    //{ v: 3, i: 2 }
    //{ v: undefined, i: 3 }
  4. Array.prototype.findIndex

    findIndexfind方法基本相同,只有返回值有区别,findIndex返回的是符合条件的元素下标,在没有这样的元素时,会返回-1

  5. keys,values,entries

    函数类型:

    type Keys = () => Iterator;
    type Values = () => Iterator;
    type Entries = () => Iterator<[number, any]>;

    keysvaluesentries都不需要任何参数,返回的都是一个迭代器。不同点在于迭代器中的值分别是数组的下标、数组的元素以及数组的下标和数组元素组成的 [ i , v ] 形式的键值对。

    const it = ['a', 'b', 'c'].entries();
    console.log(it.next()); //{ value: [ 0, 'a' ], done: false }
    console.log(it.next()); //{ value: [ 1, 'b' ], done: false }
    console.log(it.next()); //{ value: [ 2, 'c' ], done: false }
    console.log(it.next()); // { value: undefined, done: true }

你可能感兴趣的