最近看了手写数组API之后,发现数组中还有很多方法一知半解,而且数组在开发中特别常用,那么我们应该对数组的各种属性方法了然于心,才能做到游刃有余,所以今天特地出了这一期文章。
目录
1.静态属性
1.1Array[Symbol.species]
2.实例属性
2.1length
3.静态方法
3.1Array.isArray(obj)
3.2Array.of(element0[, element1[, ...[, elementN]]])
3.3Array.from(arrayLike[, mapFn[, thisArg]])
4.实例方法
4.1查询具体元素的下标
4.1.1arr.indexOf(searchElement[, fromIndex])
4.1.2arr.lastIndexOf(searchElement[, fromIndex])
4.1.3arr.includes(valueToFind[, fromIndex])
4.2查询满足条件的具体元素
4.2.1arr.find(callback[, thisArg])
4.2.2arr.findIndex(callback[, thisArg])
4.3查询是否存在满足条件的元素
4.3.1arr.some(callback[, thisArg])
4.4查询是否所有元素都满足条件
4.4.1arr.every(callback[, thisArg])
4.5添加/删除数组元素(尾)
4.5.1arr.push(element1, ..., elementN)
4.5.2arr.pop()
4.6添加/删除数组元素(头)
4.6.1arr.unshift(element1, ..., elementN)
4.6.2arr.shift()
4.7数组的排序方法
4.7.1arr.reverse()
4.7.2arr.sort()
4.8数组的转换方法
4.8.1arr.valueOf()
4.8.2arr.toString()
4.8.3arr.join([separator])
4.8.4arr.toLocalString([locales[,options]])
4.9数组的操作方法
4.9.1 arr.concat(value1[, value2[, ...[, valueN]]])
4.9.2 arr.slice([begin[, end]])
4.9.3 array.splice(start[, deleteCount[, item1[, item2[, ...]]]])
4.10数组的复制填充方法
4.10.1arr.copyWithin(target[, start[, end]])
4.10.2arr.fill(value[, start[, end]])
4.11数组的迭代方法
4.11.1arr.forEach(callback(currentValue [, index [, array]])[, thisArg])
4.11.2arr.map(callback(currentValue [, index [, array]])[, thisArg])
4.11.3arr.filter(callback(element[, index[, array]])[, thisArg])
4.12数组的归并方法
4.12.1arr.reuce(callbackFn(previousValue,currentValue[, currentIndex[, array]])[, thisArg])
4.12.1arr.reuceRight(callback(accumulator,element[, index[, array]])[, thisArg])
4.13数组的扁平化方法
4.13.1arr.flat([depth])
4.13.2arr.flatMap(function callback(currentValue[,index[,array]]){}[,thisArg])
4.14数组的迭代器方法
console.log(Array[Symbol.species])//ƒ Array() { [native code] }
console.log(Array[Symbol.species]===Array.prototype.constructor)//true
let arr=[1,5,2]
console.log(arr.length)//3
console.log(Array.isArray([]))//true
console.log(Array.isArray(new Array()))//true
console.log(Array.isArray(Array.prototype))//true
console.log(Array.isArray())//false
console.log(Array.isArray({}))//false
console.log(Array.isArray(null))//false
console.log(Array.isArray(undefined))//false
注意:其实Array.prototype也是一个数组
3.2Array.of(element0[, element1[, ...[, elementN]]])
console.log(Array.of(7))//[7]
console.log(Array.of(7,5,4))//[7,5,4]
Array(7)是创建一个长度为7的空数组,传入一个正数数值参数的时候默认指定数组的长度。那如果我们就是想创建一个具有单个元素7的数组怎么办呢,Array.of()为我们提供了解决办法。
而Array.of(7)是创建一个具有单个元素7的数组。
mapFn
时 this
对象。可迭代对象即为实现了iterable接口的对象,如数组,字符串,映射,集合,arguments,NodeList等DOM集合类型。
伪数组对象如arguments对象和NodeList等DOM集合类型,有length属性和若干索引属性,但是没有数组的方法,故叫伪数组对象。
将字符串转换为字符串数组
console.log(Array.from("abc2hyu"))//["a","b","c","2","h","y","u"]
数组的合并去重
function combine(){
let arr=[].concat.apply([],arguments)
return Array.from(new Set(arr))
}
let array = [2, 5, 9];
console.log(array.indexOf(2,0)); // 0
console.log(array.indexOf(2,1)); // -1
console.log(array.indexOf(9,3)); // -1
console.log(array.indexOf(9,2)); // 2
console.log(array.indexOf(9,-100)); // 2
console.log(array.indexOf(9,-1)); // 2
fromIndex
处开始。 let array = [2, 5,2, 9];
console.log(array.lastIndexOf(2,1)); // 0
console.log(array.lastIndexOf(2)); // 2
console.log(array.lastIndexOf(2,-3)); // 0
console.log(array.lastIndexOf(2,-9)); // -1
console.log(array.lastIndexOf(2,100)); // 2
true
,否则返回 false
。valueToFind
:需要查找的元素值。
let array = [2, 5,2, 9];
console.log(array.lastIndexOf(2,1)); // 0
console.log(array.lastIndexOf(2)); // 2
console.log(array.lastIndexOf(2,-3)); // 0
console.log(array.lastIndexOf(2,-9)); // -1
console.log(array.lastIndexOf(2,100)); // 2
arr.find(callback[, thisArg])
callback
:在数组每一项上执行的函数,接收 3 个参数:
element
:当前遍历到的元素。
index:
可选参数当前遍历到的索引。array:
可选参数,数组本身。thisArg:
可选参数执行回调时用作this
的对象。需求:查找user中是否有age为18的用户,有则返回第一个用户的信息,否则返回undefined
let user = [
{ name: "ct", age: 18 },
{ name: "cx", age: 19 },
{ name: "ca", age: 18 }
]
console.log(user.find((value) => { return value.age === 18 }))//{ name: "ct", age: 18 }
arr.findIndex(callback[, thisArg])
返回数组中满足提供的测试函数的第一个元素的索引。若没有找到对应元素则返回-1。
callback
:在数组每一项上执行的函数,接收 3 个参数:
element
:当前遍历到的元素。
index:
可选参数当前遍历到的索引。array:
可选参数,数组本身。thisArg:
可选参数执行回调时用作this
的对象。需求:查找user中是否有age为18的用户,有则返回第一个用户的下标,否则返回-1
let user = [
{ name: "ct", age: 18 },
{ name: "cx", age: 19 },
{ name: "ca", age: 18 }
]
console.log(user.findIndex((value) => { return value.age === 18 }))//0
arr.some(callback[, thisArg])
callback
:在数组每一项上执行的函数,接收 3 个参数:
element
:当前遍历到的元素。
index:
可选参数当前遍历到的索引。array:
可选参数,数组本身。thisArg:
可选参数执行回调时用作this
的对象。需求:查找user中是否存在age为18的用户,有则返回true,否则返回false
let user = [
{ name: "ct", age: 18 },
{ name: "cx", age: 19 },
{ name: "ca", age: 18 }
]
console.log(user.some((value) => { return value.age === 18 }))//true
arr.every(callback[, thisArg])
callback
:在数组每一项上执行的函数,接收 3 个参数:
element
:当前遍历到的元素。
index:
可选参数当前遍历到的索引。array:
可选参数,数组本身。thisArg:
可选参数执行回调时用作this
的对象。需求:查找user中是否所有的用户age都为18,是则返回true,否则返回false
let user = [
{ name: "ct", age: 18 },
{ name: "cx", age: 19 },
{ name: "ca", age: 18 }
]
console.log(user.every((value) => { return value.age === 18 }))//true
elementN
被添加到数组末尾的元素。
需求:向arr数组中添加元素"cx",将arr和arr1合并
let arr = [1, 2, 3]
let arr1 = [8, 9, 10]
console.log(arr.push("cx"))//4
console.log(arr)//[1,2,3,"cx"]
// 通常与apply,call一起使用
// 合并数组
console.log(Array.prototype.push.apply(arr, arr1))//7
console.log(arr)//[1,2,3,"cx",8,9,10]
注意:此处的合并数组和前面Array.from()中的合并数组实现不一样,请多多留心。
push
方法具有通用性。该方法和 call(),apply()一起使用时,可应用在类似数组的对象上。也可以像数组一样使用对象,借用call,将对象作为this传进去,让其以为我们在操作数组。 var obj = {
length: 0,
addElem: function addElem(elem) {
[].push.call(this, elem);
}
};
obj.addElem({});
obj.addElem({});
console.log(obj.length);//2
console.log(obj);//{0:{},1:{},length:2,addElem:f}
需求:向arr数组删除最后一个元素
let arr = [1, 2, 9]
console.log(arr.pop())//9
注意:从数组中删除的元素(当数组为空时返回 undefined)。
elementN
被添加到数组头部的元素需求:向arr数组头部中添加元素"cx","ct"
let arr = [1, 2, 3]
console.log(arr.unshift("cx","ct"))//5
console.log(arr)//["cx","ct",1,2,3]
需求:向arr数组删除第一个元素
let arr = [1, 2, 9]
console.log(arr.pop())//1
let arr = [1, 2, 3]
console.log(arr.reverse())//[3,2,1]
compareFunction
可选参数:用来指定按某种顺序进行排列的函数。如果省略,元素按照转换为的字符串的各个字符的Unicode位点进行排序。 firstEl
:第一个用于比较的元素。
secondEl
:第二个用于比较的元素。
compareFunction
,那么元素会按照转换为的字符串的诸个字符的Unicode位点进行排序。compareFunction
,那么数组会按照调用该函数的返回值排序。即 a 和 b 是两个将要被比较的元素:compareFunction(a, b)
小于 0 ,那么 a 会被排列到 b 之前;compareFunction(a, b)
等于 0 , a 和 b 的相对位置不变。备注: ECMAScript 标准并不保证这一行为,而且也不是所有浏览器都会遵守(例如 Mozilla 在 2003 年之前的版本);compareFunction(a, b)
大于 0 , b 会被排列到 a 之前。 let arr2=[20,5,71,6]
console.log(arr2.sort())//[20,5,6,71]
console.log(arr2.sort((a,b)=>{return a-b}))//升序排列[5,6,20,71]
数组对象也可以按照某个属性进行排序
var items = [
{ name: 'Edward', value: 21 },
{ name: 'Sharpe', value: 37 },
{ name: 'And', value: 45 },
{ name: 'The', value: -12 },
{ name: 'Magnetic' },
{ name: 'Zeros', value: 37 }
];
items.sort(function (a, b) {
return (a.value - b.value)
});
不只是数组,所有的对象都有下列三个方法toString(),toLocalString(),valueOf()方法。
let arr3=[2,54,21]
console.log(arr3.valueOf())//[2,54,21]
let arr3=[2,54,21]
console.log(arr3.toString())//'2,54,21'
注意:有没有觉得我们这个方法和join方法很像,同样是返回一个字符串,但是我们的join方法可以指定字符串中间的分割符号。
separator
:可选参数,指定一个字符串来分隔数组的每个元素。如果需要,将分隔符转换为字符串。如果缺省该值,数组元素用逗号(,
)分隔。如果separator
是空字符串(""
),则所有元素之间都没有任何字符。
var a = ['Wind', 'Rain', 'Fire'];
var myVar1 = a.join(); // myVar1的值变为"Wind,Rain,Fire"
var myVar2 = a.join(', '); // myVar2的值变为"Wind, Rain, Fire"
var myVar3 = a.join(' + '); // myVar3的值变为"Wind + Rain + Fire"
var myVar4 = a.join(''); // myVar4的值变为"WindRainFire"
arr.length
为0,或者元素为 undefined
或 null
,它会被转换为空字符串。toLocaleString
方法转成字符串,这些字符串将使用一个特定语言环境的字符串(例如一个逗号 ",")隔开。locales
:可选参数,带有BCP 47语言标记的字符串或字符串数组,关于locales
参数的形式与解释,请看Intl页面。options
:可选参数,一个可配置属性的对象。 var prices = ['¥7', 500, 8123, 12];
console.log(prices.toLocaleString('ja-JP', { style: 'currency', currency: 'JPY' }));
// "¥7,¥500,¥8,123,¥12"
这个方法里面还有很多配置,很复杂,可以去看对应的官网。
valueN
参数,则 concat
会返回调用此方法的现存数组的一个浅拷贝。var arr = ['a', 'b', 'c'];
var arr1 = arr.concat(1, [2, 3]);
console.log(arr1);// ['a', 'b', 'c', 1, 2, 3]
注意:返回一个浅拷贝,它包含与原始数组相结合的相同元素的副本。 原始数组的元素将复制到新数组.
begin
和 end
决定的原数组的浅拷贝(包括 begin
,不包括end
)。原始数组不会被改变。begin:
可选参数,提取起始处的索引(从 0
开始),从该索引开始提取原数组元素。
如果该参数为负数,则转换为正数,length+begin。
如果省略 begin
,则 slice
从索引 0
开始。
如果 begin
超出原数组的索引范围,则会返回空数组。
end
:可选参数,提取终止处的索引(从 0
开始),在该索引处结束提取原数组元素。
end
被省略或者大于或等于数组长度,则 slice
会一直提取到原数组末尾。start:
指定修改的开始位置(从0计数)。
deleteCount
:可选参数,整数,表示要移除的数组元素的个数。
deleteCount
被省略了,或者它的值大于等于array.length - start
(也就是说,如果它大于或者等于start
之后(包括start)的所有元素的数量),那么start和
之后数组的所有元素都会被删除。deleteCount
是 0 或者负数,则不移除元素。这种情况下,至少应添加一个新元素。item1, item2, ...:
可选参数,要添加进数组的元素,从start
位置左侧开始添加。如果不指定,则 splice()
将只删除数组元素。 var prices = ['¥7', 500, 8123, 12];
prices.splice(0,-1,8,9)
console.log(prices)//[8, 9, '¥7', 500, 8123, 12]
prices.splice(0,2)
console.log(prices)//['¥7', 500, 8123, 12]
target:0 为基底的索引,复制序列到该位置。
如果是负值,则转换为正数,length+begin,如果转换后还是为负数,则表示开始位置为0.
如果 target
大于等于 arr.length
,将不会发生拷贝。
如果 target
在 start
之后,复制的序列将被修改以符合 arr.length
。
start:
0 为基底的索引,开始复制元素的起始位置。
start
被忽略,copyWithin
将会从0开始复制。end
被忽略,copyWithin
方法将会一直复制至数组结尾(默认为 arr.length
)。copyWithin
将会拷贝到该位置,但不包括 end
这个位置的元素。[1, 2, 3, 4, 5].copyWithin(-2)
// [1, 2, 3, 1, 2]
[1, 2, 3, 4, 5].copyWithin(0, 3)
// [4, 5, 3, 4, 5]
[1, 2, 3, 4, 5].copyWithin(0, 3, 4)
// [4, 2, 3, 4, 5]
[1, 2, 3, 4, 5].copyWithin(-2, -3, -1)
// [1, 2, 3, 3, 4]
value
:用来填充数组元素的值。
start:
可选参数起始索引,默认值为0。
如果是负值,则转换为正数,length+begin,如果转换后还是为负数,则表示开始位置为0.
end
:可选参数终止索引,不包括终止索引,默认值为 this.length
。
如果是负值,则转换为正数,length+begin。
[1, 2, 3].fill(4); // [4, 4, 4]
[1, 2, 3].fill(4, 1); // [1, 4, 4]
[1, 2, 3].fill(4, 1, 2); // [1, 4, 3]
[1, 2, 3].fill(4, 1, 1); // [1, 2, 3]
[1, 2, 3].fill(4, 3, 3); // [1, 2, 3]
[1, 2, 3].fill(4, -3, -2); // [4, 2, 3]
主要有forEach,map,filter,some和evey我们在前面已经说过了,不再赘述了。
callback
:为数组中每个元素执行的函数,该函数接收一至三个参数:
array
可选参数正在操作的数组。index:
可选参数,数组中正在处理的当前元素的索引。currentValue
:数组中正在处理的当前元素。thisArg
:可选参数。当执行回调函数 callback
时,用作 this
的值。想要实现这种效果,就不能用箭头函数当回调函数,因为箭头函数没有this,也不能通过call,apply,bind改变内部的this,其this是由外部定义的执行上下文的this决定的。
null
或 undefined或者省略了
,this
则指向全局对象thisArg
参数有值,则每次 callback
函数被调用时,this
都会指向 thisArg
参数forEach()
遍历的范围在第一次调用 callback
前就会确定。forEach
后添加到数组中的项不会被 callback
访问到。(增)callback
的值是 forEach()
遍历到他们那一刻的值。(改)var words = ['one', 'two', 'three', 'four'];
words.forEach(function(word) {
console.log(word);
if (word === 'two') {
words.shift();
}
});
//删除后,数组整个往前移动,变成["two","three","four"],而索引1和2已经被遍历过,所以会跳过,所以three不会被打印
// one
// two
// four
callback
:为数组中每个元素执行的函数,该函数接收一至三个参数:
array
可选参数正在操作的数组。index:
可选参数,数组中正在处理的当前元素的索引。currentValue
:数组中正在处理的当前元素。thisArg
:可选参数。当执行回调函数 callback
时,用作 this
的值。想要实现这种效果,就不能用箭头函数当回调函数,因为箭头函数没有this,也不能通过call,apply,bind改变内部的this,其this是由外部定义的执行上下文的this决定的。
null
或 undefined或者省略了
,this
则指向全局对象thisArg
参数有值,则每次 callback
函数被调用时,this
都会指向 thisArg
参数map()
遍历的范围在第一次调用 callback
前就会确定。callback
访问到。(增)callback
的值是 map()
遍历到他们那一刻的值。(改)var numbers = [1, 4, 9];
var doubles = numbers.map(function(num) {
return num * 2;
});
// doubles数组的值为: [2, 8, 18]
// numbers数组未被修改: [1, 4, 9]
callback
:为数组中每个元素执行的函数,该函数接收一至三个参数:
array
可选参数正在操作的数组。index:
可选参数,数组中正在处理的当前元素的索引。currentValue
:数组中正在处理的当前元素。thisArg
:可选参数。当执行回调函数 callback
时,用作 this
的值。想要实现这种效果,就不能用箭头函数当回调函数,因为箭头函数没有this,也不能通过call,apply,bind改变内部的this,其this是由外部定义的执行上下文的this决定的。
null
或 undefined或者省略了
,this
则指向全局对象thisArg
参数有值,则每次 callback
函数被调用时,this
都会指向 thisArg
参数filter()
遍历的范围在第一次调用 callback
前就会确定。callback
访问到。(增)callback
的值是 filter()
遍历到他们那一刻的值。(改)function isBigEnough(element) {
return element >= 10;
}
var filtered = [12, 5, 8, 130, 44].filter(isBigEnough);
// filtered is [12, 130, 44]
reduce和reduceRight
previousValue
,currentValue
[, currentIndex
[, array]])[, initialValue
])callbackFn
:包含四个参数,reduce
对于数组中第一个元素之后的每一个元素,按升序各调用一次回调函数。(故只有一个参数且没提供initialValue,或者空数组提供了initialValue但是数组为空,那么此唯一值被返回,且callbackFn不执行)
previousValue
:上一次调用 callbackFn
时的返回值。currentValue
:数组中正在处理的元素。currentIndex
:可选参数,数组中正在处理的元素的索引。若指定了初始值 initialValue
,则起始索引号为 0,否则从索引 1 起始。array
:可选参数,用于遍历的数组。initialValue
可选参数:作为第一次调用 callbackFn
函数时参数 previousValue 的值。
initialValue
,则previousValue
即为 initialValue的值,然后currentValue
则将使用数组第一个元素;previousValue
将使用数组第一个元素,而 currentValue
将使用数组第二个元素。reduce
或 reduceRight
且未提供初始值(例如 [].reduce( (acc, cur, idx, arr) => {} )
)的话,会导致类型错误 TypeError: reduce of empty array with no initial value
。let sum = [0, 1, 2, 3].reduce(function (previousValue, currentValue) {
return previousValue + currentValue
}, 0)
// sum is 6
initialValue
])callback
:包含四个参数,reduce
对于数组中第一个元素之后的每一个元素,按升序各调用一次回调函数。(故只有一个参数且没提供initialValue,或者空数组提供了initialValue但是数组为空,那么此唯一值被返回,且callback不执行)
callback
时的返回值。initialValue
,则起始索引号为 0,否则从索引 1 起始。array
:可选参数,用于遍历的数组。initialValue
可选参数:作为第一次调用 callback
函数时参数 previousValue 的值。
initialValue
,则accumulator即为 initialValue的值,然后
element则将使用数组最后一个元素;reduce
或 reduceRight
且未提供初始值(例如 [].reduce( (acc, cur, idx, arr) => {} )
)的话,会导致类型错误 TypeError: reduce of empty array with no initial value
。var sum = [0, 1, 2, 3].reduceRight(function(a, b) {
return a + b;
});
// sum is 6
reduce和reduceRight只是遍历索引的顺序不一样,reduce是升序遍历索引,reduceRight是降序遍历索引。
关于initialValue和arr的值在这做个总结
depth:
可选参数指定要提取嵌套数组的结构深度,默认值为 1。也就是数组里面有数组我就展开,但是展开后的情况我管不了。2就是数组展开后里面还有数组,我也可以展开,但是二次展开后的情况我也管不了。故depth越大,展开的层数越多。
var arr1 = [1, 2, [3, 4]];
arr1.flat();
// [1, 2, 3, 4]
var arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat();
// [1, 2, 3, 4, [5, 6]]
var arr3 = [1, 2, [3, 4, [5, 6]]];
arr3.flat(2);
// [1, 2, 3, 4, 5, 6]
//使用 Infinity,可展开任意深度的嵌套数组
var arr4 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];
arr4.flat(Infinity);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
//flat() 方法会移除数组中的空项:
var arr4 = [1, 2, , 4, 5];
arr4.flat();
// [1, 2, 4, 5]
flatMap
通常在合并成一种方法的效率稍微高一些。相当于arr.map.flat(1)depth
值为1。callback
:可以生成一个新数组中的元素的函数,可以传入三个参数:
currentValue
:当前正在数组中处理的元素
index:
可选参数,数组中正在处理的当前元素的索引。
array:
可选参数,被调用的 map
数组
thisArg:
可选参数,执行 callback
函数时 使用的this
值。
var arr1 = [1, 2, 3, 4];
arr1.map(x => [x * 2]);
// [[2], [4], [6], [8]]
arr1.flatMap(x => [x * 2]);
// [2, 4, 6, 8]
// only one level is flattened
arr1.flatMap(x => [[x * 2]]);
// [[2], [4], [6], [8]]
values,keys,entries方法,这三个方法目前没了解多少,稍后会完善。
数组中改变原数组的方法有splice,pop,push,shift,unshift,sort,reverse这几个方法会改变原数组,其他的方法都不会改变原数组。