数组的基本特点和操作
数组的存储性能比普通对象要好,数组的类型也是对象。
普通对象是使用字符串作为属性名的,而数组是使用数字来作为索引来操作元素。索引:从0开始的整数就是索引。
获取数组的长度 arr.length
修改数组的长度(修改length)
- 如果修改的length大于原长度,则多出部分会空出来,置为 null。
- 如果修改的length小于原长度,则多出的元素会被删除,数组将从后面删除元素。
var arr1 = [11, 12, 13]; var arr2 = [21, 22, 23]; arr1.length = 1; // [11] arr2.length = 5; // [21,22,23,null,null]
判断是否为数组 Array.isArray(arr)
还可以通过 A instanceof B来判断 A 是否属于 B 类型。(现在用得不多)
判断数组是否包含指定值 arr.includes()
[1, 2, 3].includes(2); // true // 第二个参数表示搜索的起始位置,默认为 0 。如果第二个参数为负数,则表示倒数的位置,如果这时它大于数组长度(比如第二个参数为 -4 ,但数组长度为 3 ),则会重置为从 0 开始。 [1, 2, 3].includes(3, 3); // false
创建数组
方式 1 - 字面量
let arr1 = []; let arr2 = [1,2,3];
方式 2 - 新建数组实例
let arr1 = new Array(); // 参数为空,得到一个空数组 [] let arr2 = new Array(4); // 参数为一个数值时表示数组的长度,得到 [null,null,null,null] let arr3 = new Array(15, 16, 17); // 参数为多个数值时表示数组中的元素,得到[15,16,17]
方式 3 - Array.of()
将一系列值转换成数组
let arr = Array.of(1, 'abc', true);
方式 4 - 伪伪数组变真数组
https://blog.csdn.net/weixin_41192489/article/details/116642962
遍历数组
for of 遍历(推荐)
for…of 可以避免开拓内存空间,增加代码运行效率
for (let item of arr) { console.log(item); }
可以使用break 或 return 提前跳出遍历
for(let item of arr){ if(item === 'a'){ console.log(item) break } }
默认for…of无法获取数组元素的下标index,若想获取index,请参考
https://blog.csdn.net/weixin_41192489/article/details/116645563
forEach() 遍历
arr.forEach((item, index, arr) => { });
没有返回值,也无法被 break打断
- 第一个参数——当前正在遍历的元素
- 第二个参数——元素的索引
- 第三个参数——正在遍历的数组
使用return可以跳出当前循环,但不能跳出整个循环
let arr = ['a', 'b', 'c', 'd'] arr.forEach((item, index) => { if (item === 'b') { return } console.log(item) }) // 得到 a c d
通过throw抛异常,可以提前跳出整个循环,但不推荐
let arr = ['a', 'b', 'c', 'd'] try { arr.forEach((item, index) => { if (index === 2) { throw new Error() } console.log(item) }) } catch (e) { console.log(e) } // 得到 a b Error
for 遍历
for (var i = 0; i < arr.length; i++) { console.log(arr[i]); }
map() 遍历
对原数组中的每一项运行回调函数,将回调函数的返回结果组成新数组。
主要用于基于原数组加工生成一个新数组,新数组和原数组的长度相同。
let arr = ['a', 'b', 'c', 'd'] let newArr1 = arr.map((item, index) => item + index) let newArr2 = arr.map((item, index) => ({ 'index': index, 'value': item })) let newArr3 = arr.map((item, index) => { if (item === 'b') { return item } }) console.log(newArr1) console.log(newArr2) console.log(newArr3)
得到
[ 'a0', 'b1', 'c2', 'd3' ] [ { index: 0, value: 'a' }, { index: 1, value: 'b' }, { index: 2, value: 'c' }, { index: 3, value: 'd' } ] [ undefined, 'b', undefined, undefined ]
reduce() 遍历
let arr = [1, 2, 3, 4]; let sum = arr.reduce((x,y)=>x+y) //求和,10 let mul = arr.reduce((x,y)=>x*y) //求乘积,24
更多详情见 https://blog.csdn.net/weixin_41192489/article/details/116661854
every() 遍历
对数组中每一项运行回调函数,如果都返回true,就返回true;如果有一项返回false,则停止遍历,返回false。
- 第一个参数——当前正在遍历的元素
- 第二个参数——元素的索引
- 第三个参数——正在遍历的数组
let arr = ['a', 'b', 'good', 'd'] let result = arr.every((item, index, arr) => { console.log(item) if (item.length < 2) { return true } }) console.log(result) let result2 = arr.every((item, index, arr) => item.length > 0) console.log(result2)
得到 a b good false true
some() 遍历
对数组中每一项运行回调函数,只要有一项返回true,则停止遍历,返回true,若每一项都返回false,则最终返回false
- 第一个参数——当前正在遍历的元素
- 第二个参数——元素的索引
- 第三个参数——正在遍历的数组
let arr = ['a', 'b', 'good', 'd'] let result = arr.some((item, index, arr) => { console.log(item) if (item.length < 2) { return true } }) console.log(result) let result2 = arr.some((item, index, arr) => item.length < 0) console.log(result2)
得到 a true false
获取元素
数组[索引] 如果读取不存在的索引(比如元素没那么多),系统不会报错,而是返回undefined。
var arr = [21, 22, 23]; console.log(arr[0]); // 打印结果:21 console.log(arr[5]); // 打印结果:undefined
查找元素 arr.find()
找出第一个满足「指定条件返回true」的元素。一旦找到符合条件的第一个元素,将不再继续往下遍历。
let arr = [2, 3, 2, 5, 7, 6]; let result = arr.find(function (item, index) { return item > 4; //遍历数组arr,一旦发现有第一个元素大于4,就把这个元素返回 });
添加元素
- 在数组头部(左侧)插入一个或多个元素——arr.unshift("王五", "王六") 返回数组的新长度
- 在数组尾部(右侧)插入一个或多个元素——arr.push("王五", "王六") 返回数组的新长度
- 在数组指定位置(下标)添加元素—— arr[index] = '王五'
- 若index< arr.length -1 ,则是修改指定位置元素;
- 若index= arr.length 则相当于在数组尾部添加一个元素
- 若index> arr.length -1 ,则在index下标处添加元素后,arr.length -1到 index-1之间的下标都用undefined填充
删除元素
- 删除第一个元素 —— arr.shift() 返回被删除的元素
- 删除最后一个元素 —— arr.pop() 返回被删除的元素
删除所有元素——清空数组
array = []; //方式1:推荐 array.length = 0; //方式2:length属性可以赋值,在其它语言中length是只读 array.splice(0); //方式3:删除数组中所有项目
删除指定的元素—— splice ()
//范例 —— 从index为1的元素开始,一共删除三个元素,并且在 index=1 的前面追加两个元素 let arr = ["a", "b", "c", "d", "e", "f"]; let result = arr.splice(1, 3, "新增元素1", "新增元素2"); arr:["a","新增元素1","新增元素2","e","f"] result:["b","c","d"]
更多详情见 https://blog.csdn.net/weixin_41192489/article/details/116694667
拼接元素 join
数组转换成字符串
方法 1 —— arr.join()
将数组转换为字符串,返回结果为转换后的字符串(不会改变原来的数组)
参数为一个字符串,将会成为数组中元素的连接符;如果不指定连接符,则默认使用 , 作为连接符,此时和 toString()的效果是一致的。
var arr = ["a", "b", "c"]; var result1 = arr.join(); // 这里没有指定连接符,所以默认使用 , 作为连接符 var result2 = arr.join("-"); // 使用指定的字符串作为连接符
result1 =a,b,c result2 =a-b-c
方法 2 —— toString()
字符串 = 数组.toString();
获取下标
获取指定元素的下标
- indexOf(value):从前往后索引,获取 value 在数组中的第一个下标。
- lastIndexOf(value) :从后往前索引,获取 value 在数组中的最后一个下标。
可用于判断某个值是否在指定的数组中,如果没找到则返回-1。
var arr = ["a","b","c","d","e","d","c"]; console.log(arr.indexOf("c")); //从前往后,找第一个"c"在哪个位置 console.log(arr.lastIndexOf("d")); //从后往前,找第一个"d"在哪个位置
【lodash可以指定查询开始的位置】
// _.indexOf(array, value, [fromIndex=0]) _.indexOf([1, 2, 1, 2], 2); // => 1 // Search from the `fromIndex`. _.indexOf([1, 2, 1, 2], 2, 2); // => 3
获取符合条件的元素的下标 findIndex()
找出第一个满足「指定条件返回true」的元素的index。
let arr = [2, 3, 2, 5, 7, 6]; let result = arr.findIndex(function (item, index) { return item > 4; //遍历数组arr,一旦发现有第一个元素大于4,就把这个元素的index返回 });
从右到左查找【需要lodash】
var users = [ { 'user': 'barney', 'active': true }, { 'user': 'fred', 'active': false }, { 'user': 'pebbles', 'active': false } ]; _.findLastIndex(users, function(o) { return o.user == 'pebbles'; }); // => 2
数组复制
浅拷贝
let arr2 = arr1
深拷贝
// 使用 lodash var objects = [{ 'a': 1 }, { 'b': 2 }]; var deep = _.cloneDeep(objects); console.log(deep[0] === objects[0]); // => false
获取数组中的最大/最小值
1.es6拓展运算符...
Math.max(...arr)
2.es5 apply(与方法1原理相同)
Math.max.apply(null,arr)
3.for循环
let max = arr[0]; for (let i = 0; i < arr.length - 1; i++) { max = max < arr[i+1] ? arr[i+1] : max }
4.数组sort()
arr.sort((num1, num2) => { return num1 - num2 < 0 }) arr[0]
5.数组reduce
arr.reduce((num1, num2) => { return num1 > num2 ? num1 : num2} )
6. 使用lodash
_.max([4, 2, 8, 6]); // => 8
数组求和【需lodash】
_.sum([4, 2, 8, 6]); // => 20
数组截取 arr.slice()
从数组中提取指定的一个或者多个元素,将截取到的元素封装到一个新数组中返回(不会改变原来的数组)
新数组 = 原数组.slice(开始位置的索引, 结束位置的索引); //注意:包含开始索引,不包含结束索引
var arr = ["a", "b", "c", "d", "e", "f"]; var result1 = arr.slice(2); //从第二个值开始提取 var result2 = arr.slice(-2); //提取最后两个元素 var result3 = arr.slice(2, 4); //提取从第二个到第四个之间的值(不包括第四个值) var result4 = arr.slice(4, 2); //空
arr:["a","b","c","d","e","f"] result1:["c","d","e","f"] result2:["e","f"] result3:["c","d"] result4:[]
数组过滤 arr.filter()
对数组中每一项运行回调函数,该函数返回结果是true的项,将组成新的数组(返回值就是这个新的数组)。
const arr1 = [1, 3, 6, 2, 5, 6]; const arr2 = arr1.filter(item=> item > 4); //将arr1中大于4的元素返回,组成新的数组
过滤掉假值【需Lodash】
false
, null
,0
, ""
, undefined
, 和 NaN
都被认为是“假值”。
_.compact([0, 1, false, 2, '', 3]); // => [1, 2, 3]
数组排序 arr.sort()——改变原数组
let arr = [1, 10, 2, 12]; let DESarr = arr.sort((a, b) => b - a) // 降序排列 [12,10,2,1]
更多详情见 https://blog.csdn.net/weixin_41192489/article/details/116696303
数组反转 arr.reverse()——改变原数组
arr.reverse():反转数组,返回结果为反转后的数组(会改变原来的数组)
let arr = ["a", "b", "c", "d", "e", "f"]; let result = arr.reverse(); // 将数组 arr 进行反转 arr =["f","e","d","c","b","a"] result =["f","e","d","c","b","a"]
普通数组去重
方法1 —— 使用lodash
_.uniq([2, 1, 2]); // => [2, 1]
方法2 —— 遍历自己,与自己对比,有重复则删掉
//创建一个数组 var arr = [1, 2, 3, 2, 2, 1, 3, 4, 2, 5]; //去除数组中重复的数字 //获取数组中的每一个元素 for (var i = 0; i < arr.length; i++) { //console.log(arr[i]); /*获取当前元素后的所有元素*/ for (var j = i + 1; j < arr.length; j++) { //console.log("---->"+arr[j]); //判断两个元素的值是否相等 if (arr[i] == arr[j]) { //如果相等则证明出现了重复的元素,则删除j对应的元素 arr.splice(j, 1); //当删除了当前j所在的元素以后,后边的元素会自动补位 //此时将不会在比较这个元素吧,我需要在比较一次j所在位置的元素 //使j自减 j--; } } } console.log(arr);
方法3 —— 创建一个新数组,循环遍历,只要新数组中有老数组的值,就不用再添加
// 编写一个方法 去掉一个数组的重复元素 var arr = [1,2,3,4,5,2,3,4]; console.log(arr); var aaa = fn(arr); console.log(aaa); //思路:创建一个新数组,循环遍历,只要新数组中有老数组的值,就不用再添加了。 function fn(array){ var newArr = []; for(var i=0;i<array.length;i++){ //开闭原则 var bool = true; //每次都要判断新数组中是否有旧数组中的值。 for(var j=0;j<newArr.length;j++){ if(array[i] === newArr[j]){ bool = false; } } if(bool){ newArr[newArr.length] = array[i]; } } return newArr; }
对象数组去重
// arr为需要去重的对象数组 // prop为判重依据的字段名 function uniqObjArr(arr, prop) { let obj = {}; arr = arr.reduce(function (item, next) { obj[next[prop]] ? '' : obj[next[prop]] = true && item.push(next); return item; }, []); return arr }
使用范例
let arr = [{ key: '01', value: '乐乐' }, { key: '02', value: '博博' }, { key: '03', value: '淘淘' }, { key: '04', value: '哈哈' }, { key: '01', value: '乐乐' }]; arr = uniqObjArr(arr, 'key') console.log(arr); // 得到 // [ // { key: '01', value: '乐乐' }, // { key: '02', value: '博博' }, // { key: '03', value: '淘淘' }, // { key: '04', value: '哈哈' } // ]
数组拼接 arr.concat ()
新数组 = 数组1.concat(数组2, 数组3 ...)
var arr1 = [1, 2, 3]; var arr2 = ["a", "b", "c"]; var arr3 = ["朝阳", "vae"]; var result1 = arr1.concat(arr2); // [1,2,3,"a","b","c"] var result2 = arr2.concat(arr1, arr3); // ["a","b","c",1,2,3,"朝阳","vae"]
数组的交集、差集、补集、并集
var a = [1,2,3,4,5] var b = [2,4,6,8,10] var sa = new Set(a); var sb = new Set(b); // 交集 let intersect = a.filter(x => sb.has(x)); // 差集 let minus = a.filter(x => !sb.has(x)); // 补集 let complement = [...a.filter(x => !sb.has(x)), ...b.filter(x => !sa.has(x))]; // 并集 let unionSet = Array.from(new Set([...a, ...b]));
数组拆分【需Lodash】
将数组(array)拆分成多个 size
长度的区块,并将这些区块组成一个新数组。 如果array
无法被分割成全部等长的区块,那么最后剩余的元素将组成一个区块。
_.chunk(['a', 'b', 'c', 'd'], 2); // => [['a', 'b'], ['c', 'd']] _.chunk(['a', 'b', 'c', 'd'], 3); // => [['a', 'b', 'c'], ['d']]
数组覆写【需Lodash】
var array = [1, 2, 3]; _.fill(array, 'a'); console.log(array); // => ['a', 'a', 'a'] _.fill(Array(3), 2); // => [2, 2, 2] _.fill([4, 6, 8, 10], '*', 1, 3); // => [4, '*', '*', 10]
数组重组【需Lodash】
按下标重组和还原
https://www.lodashjs.com/docs/lodash.zip
var zipped = _.zip(['fred', 'barney'], [30, 40], [true, false]); // => [['fred', 30, true], ['barney', 40, false]] _.unzip(zipped); // => [['fred', 'barney'], [30, 40], [true, false]]
重置为对象
https://www.lodashjs.com/docs/lodash.zipObject
_.zipObject(['a', 'b'], [1, 2]); // => { 'a': 1, 'b': 2 }
统计分组
https://www.lodashjs.com/docs/lodash.groupBy
_.groupBy([6.1, 4.2, 6.3], Math.floor); // => { '4': [4.2], '6': [6.1, 6.3] } // The `_.property` iteratee shorthand. _.groupBy(['one', 'two', 'three'], 'length'); // => { '3': ['one', 'two'], '5': ['three'] }
数组统计【需Lodash】
https://www.lodashjs.com/docs/lodash.countBy
_.countBy([6.1, 4.2, 6.3], Math.floor); // => { '4': 1, '6': 2 } // The `_.property` iteratee shorthand. _.countBy(['one', 'two', 'three'], 'length'); // => { '3': 2, '5': 1 }
数组降维
[1,2,[1,2] ] 嵌套数组变为一维数组 [1,2,1,2]
使用lodash
https://www.lodashjs.com/docs/lodash.flatMap
function duplicate(n) { return [n, n]; } _.flatMap([1, 2], duplicate); // => [1, 1, 2, 2]
数组随机取样【需Lodash】
取一个
_.sample([1, 2, 3, 4]); // => 2
取n个
_.sampleSize([1, 2, 3], 2); // => [3, 1] _.sampleSize([1, 2, 3], 4); // => [2, 3, 1]
打乱数组 【需Lodash】
_.shuffle([1, 2, 3, 4]); // => [4, 1, 3, 2]
对象数组解析【需Lodash】
https://www.lodashjs.com/docs/lodash.partition
var users = [ { 'user': 'barney', 'age': 36, 'active': false }, { 'user': 'fred', 'age': 40, 'active': true }, { 'user': 'pebbles', 'age': 1, 'active': false } ]; _.partition(users, function(o) { return o.active; }); // => objects for [['fred'], ['barney', 'pebbles']] // The `_.matches` iteratee shorthand. _.partition(users, { 'age': 1, 'active': false }); // => objects for [['pebbles'], ['barney', 'fred']] // The `_.matchesProperty` iteratee shorthand. _.partition(users, ['active', false]); // => objects for [['barney', 'pebbles'], ['fred']] // The `_.property` iteratee shorthand. _.partition(users, 'active'); // => objects for [['fred'], ['barney', 'pebbles']]