前端新手JS语法笔记4——数组对象的增删改查

325 阅读4分钟

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) //创建一个长度为3的数组,很少用

转化

let arr = '1,2,3'.split(',') //用逗号分隔,得到[1,2,3]
let arr = '123'.split('') //用空隔开,得到[1,2,3]
Array.from('123') //将123分开,组成数组[1,2,3]
Array.from('aaa') //将aaa分开,组成数组['a','a','a']

Array.from() ,是把有0123下标,同时还有length属性的对象转化为数组,注意是转化为数组,不是伪数组

Array.from({0:'aaa' , 1:'bbb' , 2:'ccc', length:3}) 返回 {"aaa","bbb","ccc"}

如果length是 2,则返回 {"aaa","bbb"}

伪数组

伪数组的原型链中没有数组的原型,也就不具备数组的属性,所以一般拿到伪数组后,都会用Array.from()得到对应的数组

合并两个数组,得到新数组

arr3.concat(arr4) 是把4加在3的后面,arr3 和 arr4 是没有变化的

截取一个数组的一部分

arr3.slice(4) 是从第5个元素切开,保留第5个元素和后面的内容,arr3 是没有变化的

arr3.slice(0) 复制一个数组

注意,JS只提供浅拷贝(浅拷贝是啥待研究)

删数组里的元素

跟对象一样👇

let arr = ['a','b','c']
delete arr['0]
arr //返回 [empty,'b','c'],十分奇葩,含有empty的数组叫稀疏数组,有bug,不要用

如果直接改length,可以删元素吗?👇

let arr = [1,2,3,4,5]
arr.length = 1
arr // [1] ,修改length会删除元素,不要随便改length

删除元素的推荐API👇

arr.shift() //删除第一个
arr.pop() //删除最后一个
arr.splice(index,1) //删除从第index起的第一个
arr.splice(index,1,'x') //删除从第index起的第一个,并从第index位起添加'x'
arr.splice(index,1,'x','y') //删除从第index起的第一个,并从第index位起依次添加'x','y'

对象提供的函数,就叫做API

查看所有元素

查看所有属性名

let arr = [1,2,3,4,5];
arr.x = 'xxx'
Object.keys(arr) //返回  ['0','1','2','3','4','x']
for(let key in arr){console.log(`${key}:${arr[key]}`)}  //返回 ['0':1,'1':2,'2':3,'3':4,'4':5,'x':'xxx']

Object.keys(变量名) 得到所有属性名

Object.values(变量名) 得到所有属性值

仅查看数字(字符串)属性名和值

for(let i = 0; i<arr.length; i++){
	console.log(`${i}:${arr[i]}`)
} 

//自己让i从0增长到length-1

或者

arr.forEach(function(item,index){
	console.log(`${index}:${item}`)
}

//也可以用forEach/map等原型上的函数

如何理解forEach

function forEach(array,fn){
	for(let i = 0; i < array.length; i++){ //用for访问array的每一项
		fn( array[i], i , array ) //对每一项调用fn(array[i],i,array)。为什么传入array?规定,极少数情况下会用到
	}
}

for循环和forEach遍历的区别

  • for循环遍历数组时,可以随时break或continue,forEach不行
  • for循环后面是块作用域,而forEach后是函数作用域

查看单个属性

let arr=[111,222,333]
arr[0] // 返回111

索引边界

arr[arr.length] === undefinded
arr[-1] === undefinded

例子👇

for(let i = 0; i < arr.length; i++){
	console.log(arr[i].toString()) //此时会报错undefined没有tostring属性
}

查看某个元素是否在数组里

arr.indexOf(item) 存在则返回item的下标,否则返回-1

使用条件查找元素

arr.find(function(x){return x%5===0}) 找第一个五的倍数,然后返回那个元素值,但是无法返回元素的下标

使用条件查找元素的索引

arr.findIndex(function(x){return x%5===0}) 返回第一个五的倍数的元素的下标

增加数组中的元素

在尾部加元素

arr.push(newItem) 末尾增加一个newItem,返回新的长度

arr.push(item1,item2) 末尾增加item1和item2,返回新长度

在头部加元素

arr.unshift(newItem) 头部增加一个newItem,返回新的长度

arr.unshift(item1,item2) 头部增加item1和item2,返回新长度

在中间添加新元素

arr.splice(index,0,'x') 在第index+1的位置,添加'x'

arr.splice(index,0,'x','y') 在第index+1的位置,添加'x' 'y'

修改数组中的元素

arr.splice(index,1,'x') 将第index+1的位置元素替换为'x'

arr[4] = 4 将第五个元素替换为4

arr.reverse() 将数组反转,修改原数组

反转一个字符串👇

let s 'abcde';
s.split('').reverse().join('') //返回'edcba'

按照自定义顺序排序👇

let arr = [4,2,3,1];
arr.sort(function(a,b){
	if(a>b){
		return 1
	}else if(a===b){
		return 0
	}else{
		return -1
	}
})
//返回[1, 2, 3, 4]
let arr = [4,2,3,1];
arr.sort(function(a,b){
	if(a>b){
		return -1
	}else if(a===b){
		return 0
	}else{
		return 1
	}
})
//返回[4, 3, 2, 1]

例子👇

let arr = [
	{name:'小明',score:99},{name:'小红',score:94},{name:'小黄',score:100}
]
arr.sort(function(a,b){
	if(a.score > b.score){return 1}
	else if(a.score === b.score){return 0}
	else {return -1}
})

//返回 小红 小明 小黄

简化版👇

let arr = [
	{name:'小明',score:99},{name:'小红',score:94},{name:'小黄',score:100}
]
arr.sort(function(a,b){
	return a.score - b.score //主要看结果的正负号
})

//返回 小红 小明 小黄

数组变换

对数组的再加工

map n变n

例子👇

let arr = [1,2,3,4,5,6];
app.map(item => item*item);
//返回 [1,4,9,16,25,36],没有改变原数组

filter n变少👇

let arr = [1,2,3,4,5,6];
arr.filter(item => item %2 ===0 ? true :false)
// 如果是偶数,就留下,返回[2,4,6],没有改变原数组

简化写法👇

let arr = [1,2,3,4,5,6];
arr.filter(item => item %2 ===0 )
//返回[2,4,6]

reduce n变1

例子:求数组[1,2,3,4,5,6]所有值得和

方法1👇

let arr = [1,2,3,4,5,6];
let sum = 0;
for(let i=0;i<arr.length;i++){
	sum += arr[1]
}
console.log(sum) // 21,但是写法麻烦

方法2👇

let arr = [1,2,3,4,5,6];
let sum = 0;
arr.reduce((sum,item)=>{return sum+item},0)
// 21

理解思路:抢劫

例子2:用reduce求平方和

let arr = [1,2,3,4,5,6];
arr.reduce((resule,item)=>{return result.concat(item*item)},[])
//返回[1,4,9,16,25,36]

思路理解:还是抢劫

例子3:用reduce方法,保留数组里的偶数

let arr = [1,2,3,4,5,6];
arr.reduce((result,item)=>{
	if(item%2===1){
		return result
	}else{
		return result.concat(item)
	}
},[])
//返回[2,4,6]

思路理解:依然是抢劫

简写👇

let arr = [1,2,3,4,5,6];
arr.reduce((result,item)=>{
	if(item%2===1) ?
	  result
	:
		result.concat(item)
	
,[])
//返回[2,4,6]

简写👇

let arr = [1,2,3,4,5,6];
arr.reduce((result,item)=>
		result.concat(item%2 ===1 ? null)
	
,[])
//返回[2,4,6]

面试题:数组变换(比较难)

把数组

let arr = [
	{名称:'动物', id:1, parent:null},
	{名称:'狗', id:2, parent:1},
	{名称:'猫', id:3, parent:1},
]

改写为对象

{
	id:1, 名称:'动物',children:[
		{id:2,名称:'狗',children:null},
		{id:3,名称:'猫',children:null},
	]
}

思路:

3变1,可以尝试reduce

arr.reduce((result,item) =>{
	if(item.parent === null){
		result.id = item.id
		result['名称'] = item['名称']
	}else{
		result.children.push(item)
		delete item.parent
		item.children = null
	}
	return result
},{id:null,children:[]})