JS数组的增删改查和数组变换
JS 的数组不是典型数组
典型的数组
- 元素的数据类型相同
- 使用连续的内存存储
- 通过数字下标获取元素
但 JS 的数组不这样
- 元素的数据类型可以不同
- 内存不一定是连续的(对象是随机存储的)
- 不能通过数字下标,而是通过字符串下标
- 这意味着数组可以有任何 key
let arr = [1, 2, 3]
arr[‘xxx'] = 1
创建一个数组
新建
let arr = [1, 2, 3];
let arr = new Array(1, 2, 3);
let arr = new Array(3);
转化
let arr = '1, 2, 3'.split(‘,’)
let arr = '123'.split(‘’)
Array.from('123')
伪数组
let divList = document.querySelector(‘div’)
let divArray = Array.from(divList)
伪数组的原型链中并没有数组的原型。
没有数组共用属性的’数组',就是伪数组。
合并两个数组,得到新数组
arr1.concat(arr2);
截取一个数组的一部分
arr1.slice(1); //从第二个元素开始
arr1.slice(0); //全部截取
注意,JS 只提供浅拷贝
增删改查
删元素
跟对象一样
let arr = ['a', 'b', ‘c’]
delete arr['0']
arr // [empty, 'b', ‘c’]
// 神奇,数组的长度并没有变
如果直接改 length 可以删元素吗
let arr = [1, 2, 3, 4, 5];
arr.length = 1;
// 我X,居然可以???JS真操蛋
重要: 不要随便改 length
三种方法删元素
- 删除头部的元素
arr.shift(); // arr被修改,并返回被删元素
- 删除尾部的元素
arr.pop(); // arr被修改,并返回被删元素
- 删除中间的元素
arr.splice(index, 1) // 删除index的一个元素
arr.splice(index, 1, ‘x’) // 并在删除位置添加’x’
arr.splice(index, 1, ‘x’, ‘y’) // 并在删除位置添加’x’, ‘y’
查看元素
查看所有属性名
let arr = [1, 2, 3, 4, 5];
Object.keys(arr);
for (let key in arr) {
console.log(key);
}
这些都适用于对象,不适用于数组
查看数字(字符串)属性名和值
for(let i = 0; i < arr.length; i++){
console.log(`${i}: ${arr[i]}`)
}
arr.forEach(function(item, index){
console.log(`${index}: ${item}`)
}
查看单个属性
- 跟对象一样
let arr = [111, 222, 333];
arr[0];
- 索引越界
arr[arr.length] === undefined;
arr[-1] === undefined;
举例:
for (let i = 0; i <= arr.length; i++) {
console.log(arr[i].toString());
}
// 报错: Cannot read property ’toString’ of undefined
- 查看某个元素是否在数组里
arr.indexOf(item); // 存在返回索引,否则返回-1
- 使用条件查找元素
arr.find(item => item % 2 === 0); // 找第一个偶数
- 使用条件查找元素的索引
arr.findIndex(item => item % 2 === 0); // 找第一个偶数的索引
增加数组中的元素
- 在尾部加元素
arr.push(newItem); // 修改arr, 返回新长度
arr.push(item1, item2); // 修改arr, 返回新长度
- 在头部加元素
arr.unshift(newItem); // 修改arr, 返回新长度
arr.unshift(item1, item2); // 修改arr, 返回新长度
- 在中间添加元素
arr.splice(index, 0, ‘x’) // 在index处插入’x’
arr.splice(index, 0, ‘x’, ‘y’)
修改数组中的元素
- 反转顺序
arr.reserse(); // 修改原数组
- 自定义顺序
arr.sort();
arr.sort((a, b) => a - b);
arr.sort(function(a, b) {
if (a.score > b.score) {
return 1;
} else if (a.score === b.score) {
return 0;
} else {
return -1;
}
});
数组变换
map, filter 和 reduce
用个生动的图来描述下数组变换:
- map: n 变 n
let arr = [1, 2, 3, 4, 5, 6];
arr.map(item => item * item);
- filter: n 变少
let arr = [1, 2, 3, 4, 5, 6];
arr.filter(item => (item % 2 === 0 ? true : false));
arr.filter(item => item % 2 === 0);
- reduce: n 变 1
let arr = [1, 2, 3, 4, 5, 6];
arr.reduce((sum, item) => {
return sum + item;
}, 0);
// 用reduce实现map的功能
arr.reduce((result, item) => {
return result.concat(item * item);
}, []);
// 用reduce实现filter的功能
arr.reduce((result, item) => {
if (item % 2 === 1) {
return result;
} else {
return result.concat(item);
}
}, []);
// 再简化
arr.reduce((result, item) => {
item % 2 === 1 ? result : result.concat(item);
}, []);
// 再给我简化
arr.reduce((result, item) => result.concat(item % 2 === 1 ? [] : item), []);
做个题
let arr = [
{ name:’Animal’, id: 1, parent: null},
{ name:’Dog’, id: 2, parent: 1},
{ name:’Cat’, id: 3, parent: 1},
]
//数组变成对象
{
id:1, name: ‘Animal’, children: [
{ id: 2, name:’Dog’, children: null},
{ id: 3, name:’Cat’, children: null},
]
}
解法:
arr.reduce((result, item) => {
result[item.id] = item
return result
}, {})
arr.reduce((result, item) => {
if(item.parent === null) {
result.id = item.id
result[‘name’] = item['name']
}else{
result.children.push(item)
delete item.parent
item.children = null
}
return result
}, {id: null, children: []})