数组的基本特点和操作
数组的存储性能比普通对象要好,数组的类型也是对象。
普通对象是使用字符串作为属性名的,而数组是使用数字来作为索引来操作元素。索引:从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 - 伪数组变真数组
遍历数组
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,请参考
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
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"]
拼接元素 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]
更多详情见 javascript:void(0)
数组反转 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']]