参考文档
https://www.runoob.com/jsref/jsref-obj-array.html
一、常用方法
1.改变原数组
1.1 sort()
排序,sort()排序是按照字符串的Unicode码
// 按字母排序
var arr = ["George", "John", "Thomas", "James", "Adrew", "Martin"]
var newArr = arr.sort()
console.log(arr, newArr) // 都是[Adrew,George,James,John,Martin,Thomas]
// 按数字排序
var arr1 = [3,2,5,2,5,7,8,10]
var newArr1 = arr1.sort((a, b) => {
return a - b
})
console.log(arr1, newArr1) // 都是[2, 2, 3, 5, 5, 7, 8, 10]
// 按对象某个属性数字值排序
var arr2 = [ {num: 3}, {num: 1}, {num: 2}]
var newArr2 = arr2.sort((a, b) => {
return a.num - b.num
})
console.log(arr2, newArr2) // 都是[ {num: 1}, {num: 2},{num: 3}]
1.2 unshift()/push()
从前/从后插入数据
// 从后插入数据
var arr = ['sha', 'dou', 'qi']
var newArr1 = arr.push('push')
console.log(arr, newArr1) // ['sha', 'dou', 'qi', 'push'] , 4
// 从前插入数据
var newArr2 = arr.unshift('unshift')
console.log(arr, newArr2) // ['unshift', 'sha', 'dou', 'qi', 'push'] 5
1.3 shift()/pop()
删除第一个/删除最后一个元素
var arr = ['sha', 'dou', 'qi']
var newArr1 = arr.shift()
console.log(arr, newArr1) // ['dou', 'qi'] , 'sha'
var newArr2 = arr.pop()
console.log(arr, newArr2) // ['dou'] , 'qi'
1.4 splice()
删除、替换、添加数组
const arr = [1, 2, 3]
// 在索引为1的地方加入一个'haha'
const arr1 = arr.splice(1, 0, 'haha')
console.log(arr, arr1) // [1, 'haha', 2, 3], []
// 删除索引为1的'haha'
const arr2 = arr.splice(1, 1)
console.log(arr, arr2) // [1, 2, 3] , ['haha']
// 替换索引为1的'2'为'替换'
const arr3 = arr.splice(1, 1, '替换')
console.log(arr, arr3) // [1, '替换', 3] , [2]
2. 不改变改变原数组
2.1 join(‘’)
var arr = [100, 5, 24, 65, 43]
var newArr = arr.join('+')
console.log(arr, newArr)//[100, 5, 24, 65, 43] , 100+5+24+65+43
2.2 map()
遍历映射一个新数组 生成一个新数组
const arr = [1, 2, 3]
const newArr = arr.map((item, index) => {
return { id: item, index: index }
})
console.log(arr, newArr)
// [1, 2, 3],
// [
// {"id": 1, "index": 0 },
// { "id": 2, "index": 1 },
// { "id": 3, "index": 2 }
// ]
2.3 slice()
方法可从已有的数组中返回选定的元素。返回一个新的数组
const arr = [1, 2, 3, 4, 5, 6, 7]
// 从索引2到最后
const arr1 = arr.slice(2)
// 从索引2到索引4的元素
const arr2 = arr.slice(2, 4)
console.log(arr, arr1, arr2)
// [1, 2, 3, 4, 5, 6, 7] , [3, 4, 5, 6, 7] , [3, 4]
2.4 indexOf(item,start) / lastIndexOf(item,start)
数组中某个指定的元素位置。item 检索元素,start 开始检索位置, 找不到-1
var arr = [1, 5, 8, 6, 9, 3, 2, 6, 4, 7]
// 输出第一个6的下标
console.log(arr.indexOf(6)) // 3
// 第二个参数是从索引为四的检索位置数
console.log(arr.indexOf(6, 4)) // 7
console.log(arr.lastIndexOf(6)) // 7
2.5 reduce()
多种使用方法: https://www.cnblogs.com/fsg6/p/13360593.html?utm_source=tuicoolhttps://www.cnblogs.com/fsg6/p/13360593.html?utm_source=tuicool
array.reduce(function(prev, cur, index, arr), initialValue)
prev-- 必需。 或上次调用函数的返回值。
cur-- 必需。当前元素
index-- 可选。当前元素的索引
arr – 可选。被遍历的数组。
initialValue – 可选。传递给函数的初始值
初级应用
- 最常见的应用一般就是求和以及求乘积
let arr = [1,2,3,4,5]
console.log(arr.reduce((a,b) => a + b))//15
console.log(arr.reduce((a,b) => a * b))//120
高级应用
- 计算数组中每个元素出现的次数
let arr = ['name','age','long','short','long','name','name']
let arrResult = arr.reduce((pre, cur) => {
if (cur in pre) {
pre[cur]++
} else {
pre[cur] = 1
}
return pre
}, {})
console.log(arrResult) // {name: 3, age: 1, long: 2, short: 1}
- 去除数组中重复的元素
let arr = ['name','age','long','short','long','name','name']
let arrResult = arr.reduce((pre, cur) => {
if (!pre.includes(cur)) {
pre.push(cur)
}
return pre
}, [])
console.log(arrResult) // ['name', 'age', 'long', 'short']
- 对对象的属性求和
let person = [
{
name: 'xiaoming',
age: 18
}, {
name: 'xiaohong',
age: 17
}, {
name: 'xiaogang',
age: 19
}
]
let result = person.reduce((pre, cur) => {
return pre + cur.age
}, 0)
console.log(result) // 54
2.6 some()
- some() 不会对空数组进行检测。–测试空数组,返回都是false
- 如果有一个元素满足条件,则表达式返回true , 剩余的元素不会再执行检测。
const arr=[1, 2, 3, 4]
const newArr = arr.some((item, index) => {
return item > 2
})
console.log(arr, newArr) // [1, 2, 3, 4], true
2.7 every()
- every() 不会对空数组进行检测。测试空数组都返回true
- 如果所有元素都满足条件,则返回 true。
- 如果数组中检测到有一个元素不满足,则整个表达式返回 false ,且剩余的元素不会再进行检测。
var ages = [32, 33, 16, 40];
const newValue = ages.every((item, index) => {
return item >= 16
})
console.log(newValue) // true
2.8 Array.of(v1, v2, v3)
将一系列值转换成数组
const arr = Array.of(1, true, {name: 'jack'}, [123], 6);
console.log(arr);//[1, true, {name: 'jack'}, [123], 6);
2.9 find / findIndex
找出第一个满足条件返回true的元素/ 下标
2.10 concat()
连接两个或多个数组
const arr = [1, 2, 3, 4, 5]
const newArr = arr.concat([1, 2], ['a', 'b'])
console.log(arr, newArr) // [1, 2, 3, 4, 5], [1, 2, 3, 4, 5,1, 2,'a', 'b']
const arr = [1,2,5,6,7]
const result1 = arr.find((item, index, array) => {
return item === 6;
})
const result2 = arr.findIndex((item, index, array) => {
return item === 6;
})
console.log(result1, result2);//6, 3
2.11 flat(),flatMap()扁平化
如果不管有多少层嵌套,都要转成一维数组,可以用Infinity关键字作为参数。
如果原数组有空位,flat()方法会跳过空位。
var arr = [1,, [2, [3]]]
var newArr = arr.flat(Infinity)
console.log(arr, newArr) // [1,, [2, [3]]], [1, 2, 3]
flatMap()方法对原数组的每个成员执行一个函数(相当于执行Array.prototype.map()),然后对返回值组成的数组执行flat()方法。该方法返回一个新数组,不改变原数组。
// 相当于 [[2, 4], [3, 6], [4, 8]].flat()
[2, 3, 4].flatMap((x) => [x, x * 2])
// [2, 4, 3, 6, 4, 8]
2.12 includes()
该方法的第二个参数表示搜索的起始位置,默认为0。如果第二个参数为负数,则表示倒数的位置,如果这时它大于数组长度(比如第二个参数为-4,但数组长度为3),则会重置为从0开始。
[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true
2.13 fill()将一个固定值替换数组的元素。
创建一个都是0的数组
var newArray = new Array(10).fill('0')
["0", "0", "0", "0", "0", "0", "0", "0", "0", "0"]
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.fill("Runoob", 2, 4); // Banana,Orange,Runoob,Runoob
2.14 from()
1.伪数组变为真数组
2.Array.from("RUN") // ['R', 'U', 'N']
2.15 isArray判断是否是数组
Array.isArray([1, 2, 3]) // true
2.16 at(index) --返回指定索引的值,可以为负值(倒数查)–ES2022
var fruits = ["Banana", "Orange", "Apple", "Mango", "Kiwi", "Papaya"];
console.log(fruits.at(2)) // Apple
2.17 toReversed(),toSorted(),toSpliced(),with() — 对应reverse(), sort(), splice(), splice(index, 1, value)
含义和用法完全一样,唯一不同的是不会改变原数组,而是返回原数组操作后的拷贝。
ES2023引入了四个新方法 --对数组进行操作时,不改变原数组,而返回一个原数组的拷贝。
const sequence = [1, 2, 3];
sequence.toReversed() // [3, 2, 1]
sequence // [1, 2, 3]
const outOfOrder = [3, 1, 2];
outOfOrder.toSorted() // [1, 2, 3]
outOfOrder // [3, 1, 2]
const array = [1, 2, 3, 4];
array.toSpliced(1, 2, 5, 6, 7) // [1, 5, 6, 7, 4]
array // [1, 2, 3, 4]
const correctionNeeded = [1, 1, 3];
correctionNeeded.with(1, 2) // [1, 2, 3]
correctionNeeded // [1, 1, 3]
2.18 group(),groupToMap()分组
这是一个提案, 用来分组的
const array = [1, 2, 3, 4, 5];
array.group((num, index, array) => {
return num % 2 === 0 ? 'even': 'odd';
});
// { odd: [1, 3, 5], even: [2, 4] }
groupToMap()唯一的区别是返回值是一个 Map 结构,而不是对象
const array = [1, 2, 3, 4, 5];
const odd = { odd: true };
const even = { even: true };
array.groupToMap((num, index, array) => {
return num % 2 === 0 ? even: odd;
});
// Map { {odd: true}: [1, 3, 5], {even: true}: [2, 4] }
二.真伪数组
伪数组
比如arguments, 获取的dom元素(querySelectAll的话也是获取伪数组比较特殊,可以用forEach), jq选择器获取列表 等都是伪数组
伪数组转化为真数组
1.Array.from
类似数组的对象(array-like object)和可遍历(iterable)的对象(包括 ES6 新增的数据结构 Set 和 Map)。
function fn() {
const args = Array.from(arguments);
args.forEach(function (item, index) {
console.log(item, index);
})
}
fn(1, 2, 3, 4)
2.[].slice.call(lis)/Array.prototype.slice.call(lis)
function fn() {
const args = [].slice.call(arguments);
args.forEach(function (item, index) {
console.log(item, index);
})
}
fn(1, 2, 3, 4)
3.扩展运算符
任何定义了遍历器(Iterator)接口的对象(参阅 Iterator 一章),都可以用扩展运算符转为真正的数组。比array.from少【类似数组的对象(array-like object)–(谓类似数组的对象,本质特征只有一点,即必须有length属性。因此,任何有length属性的对象,都可以通过Array.from()方法转为数组,而此时扩展运算符就无法转换。)】
扩展运算符背后调用的是遍历器接口(Symbol.iterator),如果一个对象没有部署这个接口,就无法转换。
let nodeList = document.querySelectorAll('div');
let array = [...nodeList];
let arrayLike = {
'0': 'a',
'1': 'b',
'2': 'c',
length: 3
};
// TypeError: Cannot spread non-iterable object.
let arr = [...arrayLike];
三.案例
1 数组中最大值
var vals = [1,2,8,4,5,6]
var max = Math.max(...vals)
console.log(max) // 8
2 一维数组变成二维数据
var originList = [1,2,3,4,5,6,7,8,9,10];
function twoDimen(list) {
const newList = []
list.forEach((item, index) => {
const dimenIndex = Math.floor(index / 4)
if (!newList[dimenIndex]) {
newList[dimenIndex] = []
}
newList[dimenIndex].push(item)
})
return newList
}
console.log(twoDimen(originList)) // [[1,2,3,4], [5, 6, 7, 8], [9, 10]]
3 判断两个数组完全相等
- 简单的,元素简单元素的
const arr1 = [1, 2, 3, 4, 11, 32, 54, 28]
const arr2 = [32, 54, 28,1, 2, 3, 4, 11]
// 第一种
// function arrayAreEqual(arr1, arr2) {
// return JSON.stringify(arr1.sort()) === JSON.stringify(arr2.sort())
// }
// console.log(arrayAreEqual(arr1, arr2)) // truea
// 第二种 every
// function arrayAreEqual(arr1, arr2) {
// if (arr1.length != arr2.length) {
// return false
// }
// return arr1.every(item => arr2.includes(item))
// }
// console.log(arrayAreEqual(arr1, arr2)) // true
4循环数组
- for of 可以循环数组,伪数组,set, map,字符串,NodeList,TypedArray(前提得有in***接口),不能循环对象
for (let value of str) {console.log(value);} - for in(唯一)既能循环数组,也能循环对象
- for循环可以跳出函数
- forEach 跳不出函数
5多选通过id找name
var arr = [{ name: 'zhaohui', age: 20, id: '1' }, { name: 'chang', age: 17, id: '2' }, { name: 'nihao', age: 18, id: '3' }]
var arr1 = ['1', '3']
const newArr = []
arr.forEach(item => {
if (arr1.includes(item.id)) {
newArr.push({
value: item.name,
id: item.id
})
}
})
console.log('newArr', newArr) // [ {value: 'zhaohui', id: '1'}, {value: 'nihao', id: '3'}]
6 tree节点组装数据
var treeNodes = [
{ id: '1', name: '父节点1', parentId: null },
{ id: '1-1', name: '子节点1', parentId: '1' },
{ id: '2', name: '父节点2', parentId: null },
{ id: '2-2', name: '子节点2', parentId: '2' },
{ id: '3', name: '父节点3', parentId: null },
{ id: '3-3-1', name: '孙子节点1', parentId: '3-3' },
{ id: '3-3', name: '子节点3', parentId: '3' },
{ id: '3-4', name: '子节点3-4', parentId: '3' },
]
function formateTree(treeNode, parentId) {
var treeArr = []
for(let i = 0; i < treeNode.length; i++) {
const node = treeNode[i]
if (node.parentId == parentId) {
const newNode = [{ id: node.id, name: node.name, children: formateTree(treeNode, node.id) }]
treeArr.push(newNode)
}
}
return treeArr
}
console.log('formateTree', formateTree(treeNodes, null))

7 tree通过id数组递归出来相应的元素
var treeNodes = [{
id: 1,
label: '一级 1',
children: [{
id: 4,
label: '二级 1-1',
children: [{
id: 9,
label: '三级 1-1-1'
}, {
id: 10,
label: '三级 1-1-2'
}]
}]
}, {
id: 2,
label: '一级 2',
children: [{
id: 5,
label: '二级 2-1'
}, {
id: 6,
label: '二级 2-2'
}]
}, {
id: 3,
label: '一级 3',
children: [{
id: 7,
label: '二级 3-1'
}, {
id: 8,
label: '二级 3-2'
}]
}]
var treeChecked = [1, 4, 9, 3, 8]
let checkedNode = []
function getCheckNode(treeNodes) {
treeNodes.forEach(item => {
if (treeChecked.includes(item.id)) {
checkedNode.push({
id: item.id,
name: item.label
})
}
if (item.children && item.children.length > 0) {
getCheckNode(item.children)
}
})
}
getCheckNode(treeNodes)
console.log(checkedNode)
// [
// {
// "id": 1,
// "name": "一级 1"
// },
// {
// "id": 4,
// "name": "二级 1-1"
// },
// {
// "id": 9,
// "name": "三级 1-1-1"
// },
// {
// "id": 3,
// "name": "一级 3"
// },
// {
// "id": 8,
// "name": "二级 3-2"
// }
// ]
8 从数组中随机取出一个元素
var arr1 = ['22', '3', '2', '4', '6']
arr1[Math.floor(Math.random()*arr1.length)]
9 数组去重
let arr = [1, 2, 2, 4, null, null, '3', 'abc', 3, 5, 4, 1, 2, 2, 4, null, null, '3', 'abc', 3, 5, 4]
// 第一种方式,最简单
// console.log([...new Set(arr)]) // [1, 2, 4, null, "3", "abc", 3, 5]
// 第二种,循环判断没有push,当然也可以用indexOf判断
// let newArr = []
// arr.forEach(item => {
// if (!newArr.includes(item)) {
// newArr.push(item)
// }
// })
// console.log('newArr', newArr) // [1, 2, 4, null, "3", "abc", 3, 5]
// 第三种 对象属性不可重复,但是这个有问题,看返回的值,应该有两个3但是这个去完重就1个3, 因为对象属性只能是字符串么,所以用map
// let obj = {}
// let newArr = []
// arr.forEach((item, index) => {
// if (obj[item] === undefined) {
// newArr.push(item)
// }
// obj[item] = item
// })
// console.log('newArr', newArr) // [1, 2, 4, null, "3", "abc", 5]
// 第四种map容器不可重复的属性
// let newArr = []
// let newMap = new Map()
// arr.forEach(item => {
// if (!newMap.has(item)) {
// newArr.push(item)
// newMap.set(item, item)
// }
// })
// console.log('newArr', newArr) // [1, 2, 4, null, "3", "abc", 3, 5]
- 根据from的属性去重
var arr = [
{
from: '张三',
to: '河南'
},
{
from: '王二',
to: '阿里'
},
{
from: '王二',
to: '杭州'
},
{
from: '王二',
to: '山东'
},
]
function uniqueFrom(arr) {
let newMap = new Map();
return arr.filter(item => {
return !newMap.has(item.from) && newMap.set(item.from, item)
})
}
console.log(uniqueFrom(arr));
// [
// {
// from: '张三',
// to: '河南'
// },
// {
// from: '王二',
// to: '阿里'
// }
// ]
创建一个20位元素的数组
Array.from({length: 20}) // [undefined, ....]
Array(20).fill('1') // [1, ....]
[...Array(20)] // [undefined, ....]
Array.apply(null, {length: 10}) // [undefined, ....]
克隆
浅克隆
[…arr], concat, slice等都是浅度克隆
深克隆
参照对象的深度克隆
1.JSON.parse(JSON.stringify(obj))
const arr = [{name: 1, age: 18}, {name: 2, age: 19}];
const cloneArr = JSON.parse(JSON.stringify(arr));
arr[1].name = 'zhao'
console.log(arr, cloneArr) // arr的name被修改了,cloneArr没有被修改还是[{name: 1, age: 18}, {name: 2, age: 19}]
2.使用 StructuredClone
3.手动写深度克隆
待想
- 深度比较两个数组/对象完全相同,顺序不对也可以-- 项目中判断表单是否更改了
1071

被折叠的 条评论
为什么被折叠?



