目录
6. arr.reduce(callback,initValue)
原数组发生了改变
1. push()
可接收任意数量的参数,返回值是修改后的长度
2. pop() :
移除数组末尾最后一项,返回值是移除的项
3. shift()
删除原数组第一项,返回删除元素的值;数组为空则返回 undefined
4. unshift()
unshift():将参数添加到原数组开头,并返回数组的长度
改变数组顺序
1.sort()
按升序排列数组,返回值是排序以后的数组 。 小值在前,大值在后 。 但是sort() 方法比较的是字符串,即使数组内的值是数字
如果调用该方法时没有使用参数,将按字母顺序对数组中的元素进行排序,说得更精确点,是按照字符编码的顺序进行排序。要实现这一点,首先应把数组的元素都转换成字符串(如有必要),以便进行比较。
如果想按照其他标准进行排序,就需要提供比较函数,该函数要比较两个值,然后返回一个用于说明这两个值的相对顺序的数字。比较函数应该具有两个参数 a 和 b,其返回值如下:
若 a 小于 b,在排序后的数组中 a 应该出现在 b 之前,则返回一个小于 0 的值。
若 a 等于 b,则返回 0。
若 a 大于 b,则返回一个大于 0 的值。
(在return a- b 的情况下,a-b输出从小到大排序,b-a输出从大到小排序)
2.reverse():
反转数组项的顺序。
将数组转化为了字符串
1. join(),
这个方法的功能就是:将array数据中每个元素都转为字符串,用自定义的连接符分割,如果 join()里面不加任何参数,用法与toString()一样
var num = Array("hello","word");
console.log(num.join()); // 相当于 toString() hello,word
console.log(num.join("")); // helloword 无缝衔接字符串
console.log(num.join("-"));// hello-word
2. toString()
数组的toString方法,是在我们调用数组的toString方法的时候。其实是调用数组中的每个元素的toString方法,最后将结果串联起来。
[new Date(), 123, '23'].toString() // Wed May 20 2020 08:50:49 GMT+0800 (中国标准时间),123,23
[{}, 123].toString() // [object Object],123
[1,2, [3, 4]].toString() // 1,2,3,4
从上面的例子中,我们会发现一个如果是多维数组,通过toString转换出来的结果其实和一维数组调用toString转换出来的结果是一样的。这个时候我们就能考虑到数组的toString的另外一个用法就是可以将多维数组一维化(或者说是数组的扁平化),其实这个将数组进行一维化的方是有一个弊端的,就是不区分数字类型的值字符串的值举个例子:
[1, [2,3,4]].toString() // 1,2,3,4
['1', [2, '3', 4]].toString() // 1,2,3,4
原数组未发生改变
搜索查找
1. indexOf()和 lastIndexOf()
返回值是查找到的元素的索引值,没找到则返回 -1,并且比较是否相等用的是 ===
indexOf():接收两个参数:要查找的项和(可选的)表示查找起点位置的索引。其中, 从数组的开头(位置 0)开始向后查找。
lastIndexOf:接收两个参数:要查找的项和(可选的)表示查找起点位置的索引。其中, 从数组的末尾开始向前查找。
var arr = [1, 2, 3];
console.log(arr.indexOf(2)); //打印结果为1
又或者
var str = "helloworld";
console.log(str.indexOf("w")); //打印结果为5
那么,当想删除某个数组中的某个元素时,常常会这么写
var arr = [1, 2, 3];
var idx = arr.indexOf(2);
arr.splice(idx,1);
console.log(arr);
但是,indexOf真的就是好东西吗?看下面的代码。
var arr = [{name:"racyily",age:22},{name:"susan",age:18}];
var obj = {name:"susan",age:18};
console.log(arr.indexOf(obj)); //打印结果为-1
我们发现obj和arr数组中第1个元素时一样的。但是却返回-1。
再试试这个
var arr = [{name:"racyily",age:22},{name:"susan",age:18}];
var arr2 = arr[1];
console.log(arr.indexOf(arr2)); //打印结果为1
这下明白了,就是因为如果数组中存放的是对象或者数组的话,必须是该对象的引用,才可以使用indexOf得到正确的索引值。
那么,如果想判断一个对象(数组)在一个数组中是否存在(值与元素相等),如何实现呢?
https://blog.youkuaiyun.com/qq_44603011/article/details/122622083
http://实现判断一个对象(数组)在一个数组中是否存在(值与元素相等)
2. find方法(ES6新增):
返回通过测试(函数内判断)的数组的第一个元素的值
当数组中的元素在测试条件时返回 true 时, find() 返回符合条件的元素的值,之后的值不会再调用执行函数。如果没有符合条件的元素返回 undefined
let aArray = [1, 2, 3, 4];
let a= aArray.find((value)=>{
return value % 2 == 0; //2
})
3 findIndex方法(ES6新增):
返回传入一个测试条件(函数)符合条件的数组第一个元素位置
当数组中的元素在测试条件时返回 true 时, findIndex() 返回符合条件的元素的索引位置,之后的值不会再调用执行函数。 如果没有符合条件的元素返回 -1
let aArray = [1, 2, 3, 4];
let a= aArray.findIndex((value)=>{
return value % 2 == 0; //1
})
4 includes方法(ES7新增):
判断一个数组是否包含一个指定的值,如果是返回 true,否则false
该方法跟之前提到的:通常数组的indexOf方法,判断返回值是否等于-1来检查是否包含某个值。 相比之下,indexOf方法有两个缺点:
一是不够语义化,它的含义是找到参数值的第一个出现位置,所以要去比较是否不等于-1,表达起来不够直观。
二是,它内部使用严格相等运算符(===)进行判断,这会导致对NaN的误判。
[NaN].indexOf(NaN); // -1
includes使用的是不一样的判断算法,就没有这个问题。
[NaN].includes(NaN); // true
数组的迭代
1. forEach()
对数组的每一项运行给定函数,该方法没有返回值
var arr = ['a','b','c']
var copy = []
arr.forEach(function(item){
copy.push(item)
})
console.log(copy)
2. some()
对数组中的每一项运行给定函数,如果该函数对任一项返回true,则返回true
var a = [1,2,3,4,5]
var b = a.some(function(current,index,array){
return current > 4
})
var c = a.some(function(current,index,array){
return current > 5
})
console.log(b) // true
console.log(c) // false
3. every()
对数组中的每一项运行都给定函数,如果该函数对每一项都返回true,则返回true
var a = [1,2,3,4,5]
var b = a.every(function(current,index,array){
return current < 6
})
var c = a.every(function(current,index,array){
return current < 3
})
console.log(b) // true
console.log(c) // false
4.filter():
对数组的每一项运行给定函数,返回该函数会返回true的项组成的数组
var a = [1,2,3,4,11]
// 第一个参数为一个方法,有三个参数,current:当前值 index:当前值下标 array:这个数组对象
var b = a.filter(function(current,index,array){
return current < 10
})
console.log(b) // [1,2,3,4]
console.log(a) // [1,2,3,4,11]
5. map()
对数组的每一项运行给定函数,返回每次函数调用结果所组成的数组
var a = [1,2,3,4,5]
// 参数同filter方法
var b = a.map(function(current,index,array){
return current + 1
})
console.log(b) // [2,3,4,5,6]
console.log(a) // [1,2,3,4,5]
6. arr.reduce(callback,initValue)
reduce 为数组中的每一个元素依次执行回调函数callback,callback接收四个参数值 callback(pre,cur,index,arr) pre:上一次调用返回的值,或者提供的初始值 cur:数组中当前处理的元素 index:数组中当前处理的元素的下标 arr:调用reduce函数的数组
如果reduce函数没有传初始值,那么prev初始值为数组的第一个元素
//模拟data
const data = {
person: {
friend: {
name: 'forceddd'
}
}
}
//模拟字符串
const str = 'person.friend.name'
const res = str.split('.').reduce(
(data, key) => data[key],
data
)
console.log(res);//'forceddd'
console.log(data['person']['friend']['name']) // forceddd
数组的reduce方法 - SegmentFault 思否
其他方法
1.concat()
t用于连接两个或者多个数组,该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本。
语法:arrayObject.concat(arrayX,arrayX,…,arrayX)
将参数添加到原数组中,返回值是一个新数组,原数组未发生改变
基本用法:
let arr1 = [1,2,3,4];
let arr2 = [2,3,4,5];
console.log(arr1.concat(arr2));
// 输出:[1, 2, 3, 4, 2, 3, 4, 5]
let number = 1;
let concat1 = arr1.concat(number)
console.log(concat1);
// 输出:[1, 2, 3, 4, 1]
这样的使用方式通常用来合并数组或者向数组末端添加元素,有一点像push()方法,区别在于push()方法操作的是原数组,但是concat()会返回一个新的数组。
简单数组的连接
concat方法会创建一个新的数组,数组/值在连接时保持不变。此外,对于新数组的任何操作(仅当元素不是对象引用时)都不会对原始数组产生影响,反之亦然。
也就是说concat是一个浅拷贝,但是在简单数组的场景下它像一个深拷贝
let arr1 = [1,2,3,4];
let arr2 = [2,3,4,5];
let concat1 = arr1.concat(arr2);
console.log(concat1);
// 输出:[1, 2, 3, 4, 2, 3, 4, 5]
arr2[0] = 11
console.log(concat1);
// 输出:[1, 2, 3, 4, 2, 3, 4, 5]
从代码里可以看到当arr2数组发生变化时concat1数组并没有发生变化,在数组为简单数组的场景下concat可以用作深拷贝。
复杂数组的连接(场景一)
let arr1 = [1,2,3,4];
let arr2 = [[2,3],4,5];
let concat1 = arr1.concat(arr2);
console.log(concat1);
// 输出:[1, 2, 3, 4, [2, 3], 4, 5]
arr2[0][0] = 11
console.log(concat1);
// 输出:[1, 2, 3, 4, [11, 3], 4, 5]
当连接复杂数组时,修改arr2时,concat1数组会发生变化,所以,严格意义上concat()是一种浅拷贝,只是在某些场景下看着像一个深拷贝。
复杂数组的连接(场景二)
let arr1 = [1, 2, 3, 4];
let arr2 = [[2, 3], 4, 5]
let concat1 = arr2.concat(arr1);
console.log(concat1);
// 输出[[2,3],4,5,1,2,3,4]
arr2[0] = [20, 30];
console.log(concat1);
// 输出[[2,3],4,5,1,2,3,4]
现在的场景下,当arr2数组发生变化时,concat1数组没有被影响,当前的场景和场景一很相似,只是变更值的维度不同,场景一修改的是数组第二个维度下的值,当前场景修改的是第一个纬度下的值。
深拷贝和浅拷贝遇见concat()
通常深拷贝和浅拷贝之说是对于引用数据类型而言的,引用数据类型的名和值分别存储在栈和堆中,在栈中有一个地址可以找的到堆。
浅拷贝时,复制的是栈中的地址,然后通过地址找到堆,获取堆中的数据。因此当堆中的值发生变化以后,所有指向该堆的栈通过地址找到的值都会发生变化。
使用concat()方法时会返回一个新数组,可以理解为concat()创建新的地址和新的堆,堆中的值与连接数组的值是相同的,因此在简单数组的场景下,修改原数组,concat()方法返回的新数组的值不会被影响。但是在复杂数组的场景下,因为数组有多个维度,而concat()没有递归操作,所以concat()只能是第一维度的深拷贝,当连接维度大于1的数组时,并没有创建新的栈和堆去存储第二维度数组中值,只是创建了一个新的栈去指向第二维度的数组,此时第二维度数组内的存放数据的堆是同一个,因此当堆中的值发生改变时,所有指向该堆的栈所拿到的值都会发生变化。
参考:js数组操作方法 concat
2. slice():
返回从原数组中指定开始下标到结束下标之间的项组成的新数组。slice()方法可以接受一或两个参数,即要返回项的起始和结束位置。在只有一个参数的情况下, slice()方法返回从该参数指定位置开始到当前数组末尾的所有项。如果有两个参数,该方法返回起始和结束位置之间的项——但不包括结束位置的项。
3. splice():
可以实现删除、插入和替换。返回值是删除的项构成的数组,如果未删除则返回一个空数组
删除:可以删除任意数量的项,只需指定 2 个参数:要删除的第一项的位置(即索引)和要删除的项数。例如, splice(0,2)会删除数组中的前两项。
插入:可以向指定位置插入任意数量的项,只需提供 3 个参数:起始位置(索引)、 0(要删除的项数)和要插入的项。例如,splice(2,0,4,6)会从当前数组的位置 2 开始插入4和6。
替换:可以向指定位置插入任意数量的项,且同时删除任意数量的项,只需指定 3 个参数: 起始位置(索引)、要删除的项数和要插入的任意数量的项。插入的项数不必与删除的项数相等。例 如,splice (2,1,4,6)会删除当前数组位置 2 的项,然后再从位置 2 开始插入4和6。
4. fill() 方法
fill() 方法使用一个固定值填充一个数组从其实索引到终止所引内的全部元素。不包含终止索引。返回修改后的原始数组,不创建新数组。
使用语法:array.fill(value,[,start[,end]]),2其中:
value 用来填充数组元素的值,必填
start 可选起始索引,默认值为 0
end 可选终止索引,默认值为this.length
// 当传入单个参数的时候,该方法会用该参数的值填充整个数组
var arr1 = new Array(5)
console.log(arr1.fill(1)); //[1,1,1,1,1]
var arr2 = [1, 2, 3, 4]
console.log(arr2.fill(0)); //[0,0,0,0]
// 当传入两个参数的时候,第一个参数为填充的元素,第二个为填充元素的起始位置
var arr3 = [0, 1, 2, 3, 4, 5, 6]
console.log(arr3.fill(1, 3)); //[0,1,2,1,1,1,1]
// 当传入三个参数的时候,第一个参数为填充的元素,第二个参数和第三个参数分别指填充元素的起始和终止位置,不修改终止位置元素
var arr4 = [0, 1, 2, 3, 4, 5]
console.log(arr4.fill(1, 3, 5)); //[0,1,2,1,1,5]
//如果提供的起始位置或结束位置为负数,则他们会被加上数组的长度来算出最终的位置,例如 起始位置为-1 就相当于array.length-1
var arr5 = [0, 1, 2, 3, 4, 5]
console.log(arr5.fill(1, -3));//[0,1,2,1,1,1]
var arr6 = [0, 1, 2, 3, 4, 5]
console.log(arr6.fill(1, 3, -2));//[0,1,2,1,4,5]