JavaScript 数组方法总结篇
一、数组预览图
二、会改变原数组的方法
2.1 push()
方法在数组的尾部添加一个或多个元素,并返回数组的长度
参数: item1, item2, …, itemX ,要添加到数组末尾的元素
let arr = [1,2,3];
let length = arr.push('末尾 1','末尾 2'); // 返回数组长度
console.log(arr,length)
// [1, 2, 3, "末尾 1", "末尾 2"] 5
返回值: 数组的长度
2.2 pop()
方法删除数组的最后一个元素,减小数组长度并返回它删除的值
//组合使用 push() 和 pop() 能够用 JavaScript 数组实现先进后出的栈
let stack = [];
stack.push(1,2) // 返回长度 2,这时 stack 的值是[1,2]
stack.pop() // 返回删除的值 2,这时 stack 的值是[1]
返回值: 从数组中删除的元素(当数组为空时返回 undefined)。
2.3 unshift()
方法在数组的头部添加一个或多个元素,并将已存在的元素移动到更高索引的位置来获得足够的空间,最后返回数组新的长度
let arr = [3,4,5];
let length = arr.unshift(1,2); // 返回长度是 5
console.log(arr, length)
//[1, 2, 3, 4, 5] 5
返回值: 返回数组新的长度
2.4 shift()
方法删除数组的第一个元素并将其返回,然后把所有随后的元素下移一个位置来填补数组头部的空缺,返回值是删除的元素
let arr = [1,2,3];
let item = arr.shift(); // 返回删除的值 1
console.log(arr, item)
// [2, 3] 1
返回值: 从数组中删除的元素; 如果数组为空则返回 undefined
2.5 splice()
方法是在数组中插入或删除元素的通用方法
// start 不超过数组长度(以下操作是连续的)
let arr = [1,2,3,4,5];
arr.splice(2) // arr 是[1,2],返回值是[3,4,5]
arr.splice(1,1) // arr 是[1],返回值是[2]
arr.splice(0,3) // arr 是[],返回值是[1],因为此时数组从第 0 位开始不够 3 位,所以是删除从 0 开始到最后的所有元素。
// start 大于数组长度(以下操作是连续的)
let arr = [1,2,3,4,5];
arr.splice(5) // arr 是[1,2,3,4,5],返回值是[]
arr.splice(5,3,6) // arr 是[1,2,3,4,5,6],返回值是[]
arr.splice(5,3,7) // arr 是[1,2,3,4,5,7] 返回值是[6]
// start 是负数(以下操作是连续的)
let arr = [1,2,3,4,5];
arr.splice(-3,2); // arr 是[1,2,5], 返回值是[3,4]
arr.splice(-4); // arr 是[],返回值是[1,2,5]
// 插入数组时,是插入数组本身,而不是数组元素
let arr = [1,4,5];
arr.splice(1,0,[2,3]) // arr 是[1,[2,3],4,5],返回值是[]
2.6 sort()
sort()
方法将数组中的元素排序并返回排序后的数组
var stringArray = ["Blue", "Humpback", "Beluga"];
var numberArray = [40, 1, 5, 200];
function compareNumbers(a, b){
return a - b;
}
console.log('stringArray:' + stringArray.join());
console.log('Sorted:' + stringArray.sort());
console.log('numberArray:' + numberArray.join());
// 没有使用比较函数时,数字并不会按照我们设想的那样排序
console.log('Sorted without a compare function:'+ numberArray.sort());
console.log('Sorted with compareNumbers:'+ numberArray.sort(compareNumbers));
//打印如下
// stringArray: Blue,Humpback,Beluga
// Sorted: Beluga,Blue,Humpback
// numberArray: 40,1,5,200
// Sorted without a compare function: 1,200,40,5
// Sorted with compareNumbers: 1,5,40,200
返回值: 返回排序后的数组。原数组已经被排序后的数组代替
2.7 reverse()
方法将数组中的元素颠倒顺序,返回逆序的数组
let arr = [1,2,3];
arr.reverse() // arr 是[3,2,1],返回值是[3,2,1]
返回值: 返回顺序颠倒后的数组。原数组已经被排序后的数组代替
2.8 fill()
方法用一个固定值填充一个数组中从起始索引到终止索引内的全部元素
arr.fill(value[, start[, end]])
value
用来填充数组元素的值。start
(可选) 起始索引,默认值为 0。end
(可选) 终止索引,默认值为 this.length。- 如果 start 是个负数, 则开始索引会被自动计算成为
length+start
, 其中 length 是 this 对象的length
属性值. 如果 end 是个负数, 则结束索引会被自动计算成为length+end
返回值: 修改后的数组
[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]
[1, 2, 3].fill(4, NaN, NaN); // [1, 2, 3]
[1, 2, 3].fill(4, 3, 5); // [1, 2, 3]
Array(3).fill(4); // [4, 4, 4]
//fill 方法故意被设计成通用方法, 该方法不要求 this 是数组对象。
[].fill.call({ length: 3 }, 4); // {0: 4, 1: 4, 2: 4, length: 3}
三、不改变原数组的方法
3.1 slice()
方法返回一个从开始到结束(不包括结束)选择的数组的一部分浅拷贝到一个新数组对象。且原始数组不会被修改
返回值: 一个含有提取元素的新数组
let arr = [1,2,3,4,5];
let arr1 = arr.slice(1,3); // arr 是[1,2,3,4,5], arr1 是[2,3]
let arr2 = arr.slice(-2,-1); // arr 是[1,2,3,4,5], arr2 是[4]
// 开始位置在结束位置后面,得到的数组是空
let arr3 = arr.slice(-2, -3); // arr 是[1,2,3,4,5], arr3 是[]
let arr4 = arr.slice(2, 1); // arr 是[1,2,3,4,5], arr4 是[]
//如果元素是个对象引用 (不是实际的对象),slice 会拷贝这个对象引用到新的数组里。两个对象引用都引用了同一个对象。如果被引用的对象发生改变,则新的和原来的数组中的这个元素也会发生改变。
let arr = [{name: 'xiaoming'}];
let arr1 = arr.slice(); // arr 是[{name: xiaoming}],arr1 是[{name: 'xiaoming'}]
arr1[0].name = 'xiaogang'; // arr 是[{name: 'xiaogang'}],arr1 是[{name: 'xiaogang'}]
// 对于字符串、数字及布尔值来说(不是 String、Number 或者 Boolean 对象),slice 会拷贝这些值到新的数组里。在别的数组里修改这些字符串或数字或是布尔值,将不会影响另一个数组。
let arr = [1,2,3];
let arr1 = arr.slice(); // arr 是[1,2,3],arr1 是[1,2,3]
arr1[1] = "two"; // arr 是[1,2,3],arr1 是[1,"tow",3]
// 当然,如果向两个数组任一中添加了新元素(简单或者引用类型),则另一个不会受到影响
3.2 join()
方法将数组(或一个类数组对象)中所有元素都转化为字符串并连接在一起,返回最后生成的字符串
返回值: 一个所有数组元素连接的字符串。如果 arr.length 为 0,则返回空字符串
let num = [1,2,3];
let str1 = num.join(); // 1,2,3
let str2 = num.join(', ') // 1, 2, 3
let str3 = num.join('') // 123
//所有的数组元素被转换成字符串,再用一个分隔符将这些字符串连接起来。如果元素是 undefined 或者 null, 则会转化成空字符串。
let num = [1,null,3];
let str1 = num.join(); // 1,,3
//如果数组中的元素是数组,会将里面的数组也调用 join()
let num = [[1,2],3];
let str1 = num.join('-'); // 1,2-3
// 如果数组中的元素是对象,对象会被转为[object Object]字符串
let num = [{num: 1},2,3];
let str1 = num.join('-'); // [object Object]-2-3
// 扁平化简单的二维数组
const arr = [11, [22, 33], [44, 55], 66];
const flatArr = arr.join().split(','); // ["11", "22", "33", "44", "55", "66"]
3.3 toString()
方法将数组的每个元素转化为字符串(如有必要将调用元素的 toString()
方法) 并且输出用逗号分割的字符串列表。返回一个字符串表示数组中的元素
[1,2,3].toString(); // 1,2,3
[1,[2,'c']].toString(); //1,2,c
// 以上与不使用任何参数调用 join() 方法返回的字符串是一样的。
// 以下的这个例子要跟下面的 toLocaleString 对照看
[{a:1},1,new Date()].toString() //"[object Object],1,Sat Jul 07 2018 18:43:45 GMT+0800 (中国标准时间)"
注意: 当数组和字符串操作的时候,js 会调用这个方法将数组自动转换成字符串
[1,2,3]+'abc' //1,2,3abc
返回值: 返回一个字符串表示数组中的元素
// 扁平化简单的二维数组
const arr = [11, [22, 33], [44, 55], 66];
const flatArr = arr.toString().split(','); // ["11", "22", "33", "44", "55", "66"]
3.4 toLocaleString()
数组中的元素将使用各自的 toLocaleString 方法转成字符串,这些字符串将使用一个特定语言环境的字符串(例如一个逗号 “,”)隔开
//数组中的元素将会使用各自的 toLocaleString 方法:
// Object: Object.prototype.toLocaleString()
// Number: Number.prototype.toLocaleString()
// Date: Date.prototype.toLocaleString()
let prices = ['¥7', 500, 8123, 12];
// 不带参数
prices.toLocaleString(); // "¥7,500,8,123,12"
//带参数
prices.toLocaleString('ja-JP', { style: 'currency', currency: 'JPY' }); // "¥7,500,8,123,12"
//MDN 上的举例中说是 "¥7,¥500,¥8,123,¥12",在浏览器和 Node 中验证了返回的都是 "¥7,500,8,123,12" 啊!
// 以下的这个例子要跟上面的 toString 对照看
[{a:1},1,new Date()].toLocaleString() //"[object Object],1,2018/7/7 下午 6:45:00"
返回值: 表示数组元素的字符串
3.5 concat()
它的元素包括调用 concat() 的原始数组的元素和 concat() 的每个参数,但是要注意,concat() 不会递归扁平化数组的数组,concat() 也不会修改调用的数组
[1,2,3].concat([4,5,6],[7,8,9]) // [1, 2, 3, 4, 5, 6, 7, 8, 9]
['a','b','c'].concat(1,[2,3],[[4,5]]) // ["a", "b", "c", 1, 2, 3, [4,5]]
// concat 方法不会改变 this 或任何作为参数提供的数组,而是返回一个浅拷贝,所以原始数组和新数组都引用相同的对象。 如果引用的对象被修改,新数组和原始数组都会变。
let obj = {a: 1};
let arr1 = [2,obj];
let arr2 = [1].concat(arr1);
console.log(arr1,arr2) //[2,{a:1}],[1,2,{a:1}]
//记录下上面的打印结果之后修改 obj
obj.a = 2;
console.log(arr1,arr2) ////[2,{a:2}],[1,2,{a:2}]
// 说了是浅拷贝,而且原数组也不改变,那我们就可以用它来实现数组的浅拷贝功能
let num1 = [1,2,3];
//第一种
let num2 = num1.concat();
//第二种
let num2 = [].concat(num1);
num2[0] = 'a';
console.log(num1,num2); // [1, 2, 3] ["a", 2, 3]
3.6 isArray()
用于确定传递的值是否是一个 Array
// 下面的函数调用都返回 true
Array.isArray([]);
Array.isArray([1]);
Array.isArray(new Array());
// 这里注意:Array.prototype 也是一个数组,一个属性值不是索引的数组。[constructor: ƒ, concat: ƒ, find: ƒ, findIndex: ƒ, pop: ƒ, …]
Array.isArray(Array.prototype);
// 下面的函数调用都返回 false
Array.isArray();
Array.isArray({});
Array.isArray(null);
Array.isArray(undefined);
Array.isArray(17);
Array.isArray('Array');
Array.isArray(true);
Array.isArray(false);
Array.isArray({ __proto__: Array.prototype });
四、数组遍历、映射、过滤、检测、简化等方法
4.1 forEach()
方法从头到尾遍历数组,为每个元素调用指定的函数
callback
为数组中每个元素执行的函数,该函数接收三个参数
// 1、 空元素不遍历,undefined 和 null 是会遍历的。
let numberArr = [1,2,,3];
numberArr.forEach(function (value,index,array) {
console.log(value,index,array)
})
//打印信息如下,可见空元素是不会遍历的
//1 0 [1, 2, empty, 3]
//2 1 [1, 2, empty, 3]
//3 3 [1, 2, empty, 3]
let nullArr = [1,2,null,3];
nullArr.forEach(function (value,index,array) {
console.log(value,index,array)
})
//打印信息如下,null 是会遍历的
//1 0 (4) [1, 2, null, 3]
//2 1 (4) [1, 2, null, 3]
//null 2 (4) [1, 2, null, 3]
//3 3 (4) [1, 2, null, 3]
//2、已删除的项不会被遍历到。如果已访问的元素在迭代时被删除了,之后的元素将被跳过
let numberArr = [1,2,3];
numberArr.forEach(function (value,index,array) {
if(index === 0) {
delete numberArr[2]; //删除第三项
//或者 numberArr.pop()
}
console.log(value,index,array)
})
//打印信息如下:
// 1 0 (3) [1, 2, empty]
// 2 1 (3) [1, 2, empty]
let numberArr1 = [1,2,3,4];
numberArr1.forEach(function (value,index,array) {
if(index === 1) {
numberArr1.shift() //遍历到第二项的时候,删除第一项
}
console.log(value,index,array)
})
// 打印信息如下,遍历到第二项的时候,删除第一项,会跳过第三项
// 1 0 (4) [1, 2, 3, 4]
// 2 1 (3) [2, 3, 4]
// 4 2 (3) [2, 3, 4]
// 3、forEach 遍历的范围在第一次调用 callback 前就会确定。调用 forEach 后添加到数组中的项不会被 callback 访问到。如果已经存在的值被改变,则传递给 callback 的值是 forEach 遍历到他们那一刻的值。
let arr = [1,2,3];
arr.forEach(function (value,index,array) {
if(index === 0) {
arr.push('新增的不会被遍历到')
arr[2] = 4;
}
console.log(value,index,array)
})
// 1 0 (4) [1, 2, 4, "新增的不会被遍历到"]
// 2 1 (4) [1, 2, 4, "新增的不会被遍历到"]
// 4 2 (4) [1, 2, 4, "新增的不会被遍历到"]
// 4、使用 thisArg 参数 和 箭头函数使用 thisArg
let arr = [1,2,3];
let obj = {arr: 'thisArg'}
arr.forEach(function () {
console.log(this.arr)
},obj)
// 打印三次 'thisArg'
let arr = [1,2,3];
let obj = {arr: 'thisArg'}
arr.forEach(() => {
console.log(this.arr)
},obj)
// 打印三次 undefined
// 5、forEach 无法中途退出循环,只能用 return 退出本次回调,进行下一次回调
let arr = [1,2,3];
let result = arr.forEach((value) => {
if(value == 2) {
return value;
}
console.log(value)
})
console.log(result) // undefined ,即使中间 return vlaue,也还是 undefined
//打印 value 的值如下,说明 return 并不能终止循环
// 1
// 3
4.2 map()
方法创建一个新数组,其结果是该数组中的每个元素都调用一个 callback 函数后返回的结果
- 返回值: 一个新数组,每个元素都是回调函数的结果
- 不要用
map
代替forEach
,map
会创建一个新的数组,占用内存。如果你不用map
的返回值,那你就应当使用forEach
4.3 filter()
- 方法返回的数组元素是调用的数组的一个子集。传入的函数时用来逻辑判定的,该函数返回 true 或 false,如果返回值为 true 或能转化为 true 的值,那么传递给判断函数的元素就是这个子集的成员,它将被添加倒一个作为返回值的数组中
- 返回值: 一个新的通过测试的元素的集合的数组,如果没有通过测试则返回空数组
4.4 every()
方法测试数组的所有元素是否都通过了指定函数的测试。当且仅当针对数组中的所有元素调用判定函数都返回 true,它才返回 true。
- 空数组上调用 every 方法,返回 true,因为空数组没有元素,所以空数组中所有元素都符合给定的条件
- 返回值: 一个布尔值,当所有的元素都符合条件才返回 true,否则返回 false
let arr = [12,34,5,23,44];
let num = 0;
let result = arr.every(function (element, index, array) {
num++;
return element > 10;
})
console.log(result,num) // 打印 false 3
// 可见发现 5 这个小于 10 的元素后,遍历立即终止,num 为 3
let arr = [12,34,,23,44];
let num = 0;
let result = arr.every(function (element, index, array) {
num++;
return element > 10;
})
console.log(result,num) // 打印 true 4
// 不会遍历没有赋值的索引位置,所以 num 为 4
let result = [].every(function (element, index, array) {
return element > 10;
})
console.log(result) // 打印 true
4.5 some()
方法测试数组中的某些元素是否通过由提供的函数实现的测试。当数组中至少有一个元素调用判定函数返回 true,它就返回 true,当且仅当数组中的所有元素调用判定函数都返回 false,它才返回 false
- 空数组调用 some,返回 false
- 返回值: 只要数组中的任意一个元素在回调函数中返回的是真值,就返回 true,否则为 false
// 一个简单的例子说明
function isBiggerThan10(element, index, array) {
console.log(index)
return element > 10;
}
[2, 5, 8, 1, 4].some(isBiggerThan10); // 返回值是 false,打印的 index 是 0,1,2,3,4
[12, 5, 8, 1, 4].some(isBiggerThan10); // 返回值是 true,打印的 index 是 0,找到符合元素之后立即返回
// 实现一个跟 includes 方法类似的功能
let arr = [1,2,3];
function include(value) {
return arr.some((element) => {
return element === value
})
}
include(2) // true
include(4) // false
let result = [].some(function (element, index, array) {
return element > 10;
})
console.log(result) // 打印 false
4.6 reduce() 和 reduceRight()
这两个方法使用指定的函数将数组元素进行组合,生成单个值。这在函数式编程中是常见的操作,也可以称为“注入”和“折叠”。reduceRight() 和 reduce() 工作原理是一样的,不同的是 reduceRight() 按照数组索引从高到低(从右到左)处理数组,而不是从低到高
- 如果数组为空且没有提供 initialValue,会抛出 TypeError 。如果数组仅有一个元素(无论位置如何)并且没有提供 initialValue, 或者有提供 initialValue 但是数组为空,那么此唯一值将被返回并且 callback 不会被执行
- 返回值: 函数累计处理的结果
let arr = [1,2,3,4,5];
let sum = arr.reduce((x,y) => x + y,0);
console.log(sum) // 15
// 看一下 initialValue 传和不传的区别
let arr = [1,2,3,4,5];
arr.reduce(function (accumulator,currentValue,currentIndex,arr) {
console.log(currentIndex)
return accumulator + currentValue;
})
// 1,2,3,4,5 没传入 initialValue,索引是从 1 开始
arr.reduce(function (accumulator,currentValue,currentIndex,arr) {
console.log(currentIndex)
return accumulator + currentValue;
},10)
// 0,1,2,3,4,5 传入 initialValue,索引从 0 开始
// 应用到二维数组展开
let arr = [[0, 1], [2, 3], [4, 5]].reduce(
(a, b) => a.concat(b)
);
console.log(arr)
// [0, 1, 2, 3, 4, 5]
4.7 indexof()
方法返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1
- 注意:
indexOf
使用严格相等(即===
)比较searchElement
和数组中的元素。而且indexOf()
不能识别NaN
- 返回值: 首个被找到的元素在数组中的索引位置; 若没有找到则返回 -1
let array = [2, 5, 9];
array.indexOf(2) // 0
array.indexOf(7) // -1
array.indexOf(9, 2) // 2
array.indexOf(9, 3) // -1
array.indexOf(2, -1) // -1
array.indexOf(2, -3) // 0
array.indexOf(2, -4) // 0
let array1 = [1,2,NaN];
array1.indexOf(NaN) // -1
4.8 includes()
方法用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回 false。 ES7 新增
- 返回值: 一个布尔值,根据情况,如果包含则返回 true,否则返回 false
[1, 2, 3].includes(2); // true
[1, 2, 3].includes(4); // false
[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true
[1, 2, 3].includes(3, -4); // true
[1, 2, NaN].includes(NaN); // true
4.9 find() 和 findIndex()
find 方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined。findIndex 方法返回数组中满足提供的测试函数的第一个元素的索引。否则返回-1
find
方法,当某个元素通过 callback 的测试时,返回数组中的一个值,否则返回 undefined。findIndex
方法,返回数组中满足提供的测试函数的第一个元素的索引。否则返回-1
// find
let a = [1, 4, -5, 10].find((n) => n < 0); // 返回元素-5
let b = [1, 4, -5, 10,NaN].find((n) => Object.is(NaN, n)); // 返回元素 NaN
// findIndex
let a = [1, 4, -5, 10].findIndex((n) => n < 0); // 返回索引 2
let b = [1, 4, -5, 10,NaN].findIndex((n) => isNaN(n)); // 返回索引 4
// 稀疏数组
let a =[1,,3,4];
let index = 0;
a.find((n) => {
console.log(index++) //0,1,2 第二次是 empty 也会调用一次,而且返回为 true,立即退出
return n === 3;
})
4.10 其他
keys()
方法返回一个新的 Array 迭代器,它包含数组中每个索引的键values()
方法返回一个新的 Array 迭代器,它包含数组中每个索引的值entries()
方法返回一个新的 Array 迭代器,该对象包含数组中每个索引的键/值对
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: 小程序之登录
下一篇: 彻底找到 Tomcat 启动速度慢的元凶
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论