新增的原型方法
-
Array.prototype.copyWithin
函数类型:
/** * @author: forceddd * @desc: 将数组中的,从start位置开始至end位置(不包含end处的元素)结束的元素,进行浅复制,并从target处开始覆盖该数组。最后将修改后的数组返回 * @param {number} target 复制到数组的起始覆盖位置,默认值为0 * @param {number} start 开始复制元素的位置,默认值为0 * @param {number|undefined} end 结束复制元素的位置,默认值为数组长度 * @return {any[]} 改变之后的数组 */ <T>(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 ] 复制代码
第三,当
target
、start
或者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 ] 复制代码
-
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> ] 复制代码
fill
和copyWithin
一样,返回的也是原数组,并且当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 ] ] 复制代码
-
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
执行一次,这和map
、forEach
等函数是不同的。[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 } 复制代码
-
Array.prototype.findIndex
findIndex
与find
方法基本相同,只有返回值有区别,findIndex
返回的是符合条件的元素下标,在没有这样的元素时,会返回-1
。 -
keys,values,entries
函数类型:
type Keys = () => Iterator<number>; type Values = () => Iterator<any>; type Entries = () => Iterator<[number, any]>; 复制代码
keys
,values
,entries
都不需要任何参数,返回的都是一个迭代器。不同点在于迭代器中的值分别是数组的下标、数组的元素以及数组的下标和数组元素组成的[ 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 } 复制代码