js 数组的基础知识
基本操作
声明
数组里可以存放任何类型的数据
1 2 3 4 let arr = new Arrary (0 , 1 , 2 , 3 )let newArr = [0 , 1 , 2 , 3 ]
获取元素
根据下标获取,从 0 开始
1 2 3 4 5 6 7 8 9 let arr = [0 , 1 , 2 , 3 , 4 ]cosnole.log (arr[2 ]) let arr1 = [ [1 , 2 ], [2 , 3 ], ] console .log (arr[0 ])
获取数组长度
根据 arr.length
获取数组长度
1 2 3 4 5 6 let arr = [0 , 1 , 2 , 3 , 4 ]console .log (arr.length ) arr[10 ] = 2 console .log (arr.length ) console .log (arr[7 ])
注意
使用构造函数创建数组时, 如果只填写一个为 number 类型的值,就会将此数组填充为对应长度的数组
1 2 let arr = new Array (10 )console .log (arr.length )
在 es6 以后,使用 Array.of
可以解决此问题
1 2 3 let arr = Array .of (10 )console .log (arr.length ) console .log (arr)
类型检测
可以使用 Array.isArray
检测一个数据是否是数组
1 2 3 4 5 console .log (Array .isArray ([])) console .log (Array .isArray ("" )) console .log (Array .isArray ({})) console .log (Array .isArray (1 )) console .log (Array .isArray (false ))
转换为字符串
可以使用 数组.toString
将数组转换为字符串
1 2 console .log ([].toString ()) console .log ([1 , 2 , 3 ].toString ())
使用
后端需要传递一个 id 字符串时,可以使用此方法转换
可以使用数组 String(数组)
来转换
1 console .log (String ([1 , 2 , 3 , 4 ]))
可以使用数组.join('拼接的字符')
来自定义用什么符号拼接为字符串
1 2 console .log ([1 , 2 , 3 , 4 ].join ("-" )) console .log ([1 , 2 , 3 , 4 ].join ("," ))
其他类型数据转换为数组
字符串可以使用字符串.split()
转换为数组
1 console .log ("1,3,4,6" .split ("," ))
元素中有 length 属性时,可以使用 Array.from(元素)
转换
1 2 3 const string = "whbbit.cn" console .log (Array .from (string))
Object 也可以使用此特性转换:
1 2 3 4 5 6 7 let obj = { 0 : 'whbbit.cn' 1 : 'wxw' } console .log (Array .from (obj)) obj.length = 2 console .log (Array .from (obj))
Arrar.from()有第二个参数,是对第一个元素的操作
1 2 3 4 5 6 7 8 9 10 <div > 1</div > <div > 2</div > <script > let divs = document .querySelectorAll ("div" ) Array .from (divs, (item ) => { item.style .color = "red" return item }) </script >
扩展运算符
数组拼接
1 2 3 let className = ["js" , "css" , "html" ]let numbers = [1 , 2 , 3 ]console .log ([...numbers, className])
函数传参
参数数量不确定时可以使用展开语法将所有参数接收到一个数组中
1 2 3 4 5 function sum (...rest ) { return rest.reduce ((s, v ) => (s += v), 0 ) } sum (1 , 2 , 3 , 4 )
dom 节点操作
1 2 3 4 5 6 7 8 9 10 11 <div > 1</div > <div > 2</div > <script > let divs = document .querySelectorAll ("div" ) ;[...divs].map ((item ) => { console .log (item) }) </script >
解构赋值
不使用解构赋值
1 2 3 let arr = ["wxw" , 23 ]let name = arr[0 ]let age = arr[1 ]
使用解构赋值
1 let [name, age] = ["wxw" , 23 ]
过滤某个值
1 let [, age] = ["wxw" , 23 ]
结合扩展运算符
1 let [name, ...rest] = ["wxw" , 23 , "whbbit.cn" ]
赋值默认值
1 2 3 4 function show ([name, year, site = 10 ] ) { console .log (name, year, site) } show (["wxw" , 23 ])
数组方法
数组元素添加
1 2 3 4 5 6 7 8 9 let arr = [0 , 1 ]arr[arr.length ] = [2 ] arr[arr.length ] = [3 ] arr = [...arr, 4 ] arr.push (5 ) arr.unshift (-1 ) arr = [-2 , ...arr]
数组删除元素
使用 pop()弹出数组最后一个元素,会改变原数组
1 2 3 let arr = [0 , 1 ]let val = arr.pop ()console .log (val)
使用 shift() 弹出数组第一个元素,会改变原数组
1 2 3 let arr = [0 , 1 ]let val = arr.shift ()console .log (val)
数组填充
1 console .log (new Array (3 ).fill (0 ))
在指定位置填充
1 2 3 console .log ([1 , 2 , 3 , 4 ].fill ("wxw" , 1 , 3 ))
splice
会改变原数组,返回值为受改变的元素
1 2 3 4 let arr = [0 , 1 , 2 , 3 , 4 ]let change = arr.slice (1 , 2 )console .log (change)
slice
不会改变原数组,返回值为受改变的元素
1 2 3 4 5 6 7 8 9 10 let arr = [0 , 1 , 2 , 3 , 4 ]let change = arr.slice (1 , 2 )console .log (change) change = arr.slice () console .log (change) change = arr.slice (1 ) console .log (change)
案例:移动数组元素方法
1 2 3 4 5 6 7 8 9 10 11 12 function move (array, from , to ) { if (from < 0 || to >= array.length ) { console .log ("参数错误" ) return } const newArray = [...array] let item = newArray.splice (from , 1 ) newArray.splice (to, 0 , ...item) return newArray } let array = [0 , 1 , 2 , 3 ]console .log (move (array, 1 , 3 ))
清空数组
赋值一个新数组,内存地址更改为新数组的地址。对原有内存地址数据没有改变
1 2 3 4 5 let array = [0 , 1 , 2 , 3 , 4 ]let w = arrayarray = [] console .log (array) console .log (w)
长度设置为 0,对原有内存地址数据进行操作。其他引用该地址的数据也会清空
1 2 3 4 5 let array = [0 , 1 , 2 , 3 , 4 ]let w = arrayarray.length = 0 console .log (array) console .log (w)
1 2 let array = [0 , 1 , 2 , 3 , 4 ]array.splice (0 )
1 2 let array = [0 , 1 , 2 , 3 , 4 ]while (array.pop ()) {}
数组拆分/合并
拆分
1 2 let str = "1,2" let arr = str.split ("," )
合并 concat() 或 扩展运算符
1 2 3 let arr1 = [1 , 2 , 3 ]let arr2 = [4 , 5 , 6 ]arr1.concat (arr2)
复制指定元素至指定位置 copyWithin()
查找数据
indexOf 和 lastIndexOf
indexOf
从数组左侧开始查找对应元素。元素存在就返回当前元素在数组中第一次出现的位置,不存在就返回-1
1 2 3 let arr = [1 , 2 , 3 , 4 ]console .log (arr.indexOf (2 )) console .log (arr.indexOf (8 ))
lastIndexOf
从数组右侧开始查找对应的元素。元素存在就返回当前元素最后一次出现的位置,不存在就返回 -1
1 2 3 let arr = [1 , 2 , 3 , 4 , 3 ]console .log (arr.lastIndexOf (3 )) console .log (arr.lastIndexOf (6 ))
注意
indexOf 和 lastIndexOf会进行类型匹配
1 2 3 let arr = [1 , 2 , 3 , 4 , "5" ]console .log (arr.indexOf (5 )) console .log (arr.lastIndexOf (5 ))
注意
indexOf 和 lastIndexOf可以传递第二个参数,表示从第几个元素开始查找
返回值还是该元素在数组中出现的第一次或最后一次
1 2 3 let arr = [1 , 2 , 3 , 4 , 2 ]console .log (arr.indexOf (2 , 1 )) console .log (arr.indexOf (3 , 1 ))
includes
查找对应的元素是否在对应的数组中,返回 boolean 类型
1 2 3 let arr = [1 , 2 , 3 , 4 , 5 ]console .log (arr.includes (2 )) console .log (arr.includes (10 ))
includes 实现原理
1 2 3 4 5 6 7 8 function includes (array, val ) { for (const value of array) { if (value === val) return true return false } } let array = [1 , 2 ]console .log (includes (array, 2 ))
1 2 3 4 let lesson = [{ name : "html" }, { name : "js" }, { name : "css" }]console .log (lesson.includes ({ name : "html" }))
find 和 findIndex
find
find 可以传递一个回调函数,回调函数返回值为 true 时就返回找到第一个值,回调函数返回为 false 时就返回 undefined
1 2 3 4 5 let arr = [1 , 2 , 3 ]console .log (arr.find ((item ) => true )) console .log (arr.find ((item ) => item === 2 )) console .log (arr.find ((item ) => item === "2" )) console .log (arr.find ((item ) => item === 200 ))
1 2 3 let lesson = [{ name : "html" }, { name : "js" }, { name : "css" }]console .log (lesson.find ((item ) => item.name === "html" ))
findIndex
findIndex 可以传递一个回调函数,回调函数返回值为 true 时就返回找到第一个值所在的位置,回调函数返回为 false 时就返回 -1
1 2 3 let lesson = [{ name : "html" }, { name : "js" }, { name : "css" }]console .log (lesson.findIndex ((item ) => item.name === "html" ))
自定义 find
1 2 3 4 5 6 7 8 9 function find (array, callback ) { for (const value of array) { if (callback (value)) { return value } } return undefined } find ([1 , 2 , 3 , 4 ], (item ) => item === 2 )
在原型链上定制 findValue 方法
1 2 3 4 5 6 7 Array .prototype .findValue = function (callback ) { for (const value of this ) { if (callback (value)) return value } return undefined } ;[1 , 2 , 3 , 4 ].findValue ((item ) => item === 2 )
排序
sort
回调函数返回值小于 0 两者位置互换,大于 0 不变
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 let arr = [1 , 3 , 2 , 4 , 5 ]arr.sort ((a, b ) => a - b) arr.sort ((a, b ) => b - a) let cart = [ { name : "html" , price : 20 }, { name : "css" , price : 25 }, { name : "js" , price : 30 }, ] cart = cart.sort ((a, b ) => a.price - b.price ) cart = cart.sort ((a, b ) => b.price - a.price )
sort 实现
1 2 3 4 5 6 7 8 9 10 11 12 13 function sort (array, callback ) { for (const n in array) { for (const m in array) { if (callback (array[n], array[m]) < 0 ) { ;[array[n], array[m]] = [array[m], array[n]] } } } return array } arr = sort ([2 , 3 , 1 ], (a, b ) => a - b) arr = sort ([2 , 3 , 1 ], (a, b ) => b - a)
数组循环
for 循环
1 2 3 4 5 6 7 8 9 10 11 let lessons = [ { name : "html" , price : 20 }, { name : "css" , price : 25 }, { name : "js" , price : 30 }, ] for (let i = 0 ; i < lessons.length ; i++) { console .log (lessons[i]) }
for … of
拿到的值是对应元素的值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 let lessons = [ { name : "html" , price : 20 }, { name : "css" , price : 25 }, { name : "js" , price : 30 }, ] for (const lesson of lessons) { lesson.click = true } console .log (lessons)
为什么可以改变原数组呢?
这里的 lesson 是重新赋值的一个元素,可以改变原数组是因为这是直接改变内存地址中的值
1 2 3 4 5 let arr = [1 , 2 , 3 ]for (const value of arr) { value = 3 } console .log (arr)
for … in
拿到的值是对应元素的下标
1 2 3 4 5 6 7 8 9 10 11 let lessons = [ { name : "html" , price : 20 }, { name : "css" , price : 25 }, { name : "js" , price : 30 }, ] for (const index in lessons) { console .log (lessons[index]) }
forEach
forEach 可以收两个参数,第一个参数是一个回调函数,第二个参数是 this 指向。回调函数可以接受三个参数,第一个是当先循环的元素,第二个是当前循环的下标,第三个元素是原数组
1 2 3 4 5 6 7 8 let lessons = [ { name : "html" , price : 20 }, { name : "css" , price : 25 }, { name : "js" , price : 30 }, ] lessons.forEach ((item, index, lessons ) => { console .log (item, index, lessons) })
interator 迭代器
1 2 3 4 5 6 let lessons = [ { name : "html" , price : 20 }, { name : "css" , price : 25 }, { name : "js" , price : 30 }, ] console .log (lessons.keys ().next ())
some & every
some
every
数组过滤
filter
返回符合条件的数据数组
1 2 let arr = [1 , 2 , 3 ]console .log (arr.filter ((item ) => item > 2 ))
filter 实现
1 2 3 4 5 6 7 8 9 10 11 12 let arr = [1 , 2 , 3 ]function filter (array, callback ) { let newArray = [] for (const value of array) { if (callback (value) === true ) { newArray.push (value) } } return newArray } const res = filter (arr, (item ) => item > 2 )console .log (res)
map
返回一个操作后的数组
1 2 3 let arr = [1 , 2 , 3 ]let newArr = arr.map ((item ) => item + 2 )console .log (newArr)
reduce
reduce 接收两个参数,第一个参数为一个回调函数,第二个参数是初始值
回调函数第一个值是上一次回调函数的返回值,第一次调用时 reduce 没有传递第二个参数,就默认为数组的第一个参数,第二个参数有传值就为第二个参数传递的值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 let arr = [1 , 2 , 3 , 4 , 5 ]arr.reduce ((pre, value, index, array ) => { console .log (pre, value) }) arr.reduce ((pre, value, index, array ) => { console .log (pre, value) }, 2 ) arr.reduce ((pre, value, index, array ) => { console .log (pre, value) return 22 }, 2 )
案例:统计元素出现次数
1 2 3 4 5 6 7 8 function arrayCount (array, item ) { return array.reduce ((total, cur ) => { total += item === cur ? 1 : 0 return total }, 0 ) } console .log (arrayCount ([1 , 2 , 2 , 2 , 1 , 1 , 2 ], 2 )) console .log (arrayCount ([1 , 2 , 2 , 2 , 1 , 1 , 2 ], 1 ))
案例:获取元素中的最大值
1 2 3 4 function getMaxItem (array, item ) { return array.reduce ((pre, cur ) => (pre > cur ? pre : cur)) } console .log (getMaxItem ([1 , 2 , 3 , 444 , 555 ]))
案例:获取阅读次数最多的文章
1 2 3 4 5 6 7 8 9 10 11 12 13 function max (array ) { return array.reduce ((pre, cur ) => { return pre.count > cur.count ? pre : cur }) } let article = [ { title : "js基础" , count : 100 }, { title : "css基础" , count : 200 }, { title : "ts基础" , count : 10 }, { title : "html基础" , count : 500 }, ] console .log (max (article))
案例:所有文章阅读总数
1 2 3 4 5 6 7 8 9 10 11 function count (array ) { return array.reduce ((pre, cur ) => (pre += cur.count ), 0 ) } let article = [ { title : "js基础" , count : 100 }, { title : "css基础" , count : 200 }, { title : "ts基础" , count : 10 }, { title : "html基础" , count : 500 }, ] console .log (count (article))
案例:文章阅读总数大于 200 的文章名称
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 function getTitleByCount (array, count ) { return array .reduce ((arr, cur ) => { if (cur.count > count) { arr.push (cur) } return arr }, []) .map ((item ) => item.title ) } let article = [ { title : "js基础" , count : 100 }, { title : "css基础" , count : 200 }, { title : "ts基础" , count : 10 }, { title : "html基础" , count : 500 }, ] console .log (getTitleByCount (article, 200 ))
案例: 数组去重
使用 reduce
1 2 3 4 5 6 7 8 let arr = [1 , 2 , 2 , 2 , 3 , 34 , 4 , 1 , 1 , 1 , 2 , 3 , 4 , 5 ]let result = arr.reduce ((arr, cur ) => { if (!arr.includes (cur)) { arr.push (cur) } return arr }, []) console .log (result)
使用扩展运算符和 Set
1 2 3 let arr = [1 , 2 , 2 , 2 , 3 , 34 , 4 , 1 , 1 , 1 , 2 , 3 , 4 , 5 ]let result = [...new Set ([...arr])]console .log (result)