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: []})
comments powered by Disqus