1、JS的数组
- 数组对象,是一种特殊的对象
- JS其实没有真正的数组,只是用对象模拟数组
- JS的数组
- 元素的数据类型可以不同
- 内存不一定是连续的(对象是随机存储的)
- 不能通过数字下标,而是通过字符串下标
- 这意味着数组可以有任何key,如
let arr = [1,2,3]
arr['xxx'] = 1
Object.keys(arr) //["0","1","2","xxx"]
2、创建数组
- 创建方法
let arr = [1,2,3] //1
let arr = new Array(1,2,3) //2
let arr = new Array(3) //3
- 转化(把字符串或对象转化为数组,但原来的值不变)
let arr = '1,2,3'; arr.split(',') //['1','2','3']
let arr = '123'; arr.split('') //['1','2','3']
Array.from('123') //['1','2','3']
3、伪数组
- let divList = document.querySelectorAll('div')
- 伪数组的原型链中并没有数组的原型,如
arr = {0:'a',1:'b',2:'c',length:3} //这是一个伪数组
- 没有数组属性的“数组”,就是伪数组
- 拿到伪数组的时候,要把它转化为数组
3、其他创建数组的方法
- 合并两个数组,获得一个新的数组
arr1.concat(arr2)
- 截取一个数组的一部分,不改变原来的数组
let arr1 = [1,2,3]
arr1.slice(1) //从第二个元素开始,[2,3]
arr1.slice(0) //全部截取,用于复制数组,[1,2,3]
let arr2 = arr1.slice(0) //复制数组
arr1 = [1,2,3] //arr1没有变化
- 注意:JS只提供浅拷贝
4、增加数组中的元素
- 在尾部增加元素
arr.push('x') //修改arr,返回新的长度
arr.push('x','y') //修改arr,在尾部增加元素'x','y',返回新的长度
- 在头部加元素
arr.unshift('x') //修改arr,在头部增加元素'x',然后返回新长度
arr.unshift('x','y')
- 在中间加元素
arr.splice(index,0,'x') //在数组下标为index的前面插入'x'
arr.splice(index,0,'x','y') //在数组下标为index的前面插入'x'
- 实例:
5、删除数组中的元素
- 跟对象一样
let arr = ['a','b','c']
delete arr['0']
arr //[empty,'b','c'],length=3
神奇,数组的长度并没有变
- 稀疏数组:有length长度,元素大多为empty的数组
- 如果直接改length,可以删除元素吗?
let arr = [1,2,3,4,5]
arr.length = 1
arr //arr===[1],真的可以,但是会报错
- 重要:不要随便改length
- 正确的删除方法:
- 删除头部的元素
arr.shift() //arr被修改,并返回被删元素
示例:
- 删除尾部的元素
arr.pop() //arr被修改,并返回被删元素
示例:
- 删除中间的元素
arr.splice(x,1) //删除arr[x]的一个元素
arr.splice(x,1,'x') //并在删除位置添加'x'
arr.splice(x,1,'x','y') //并在删除位置添加'x','y'
示例:
6、修改数组中的元素
- 反转顺序
arr.reverse() //翻转顺序,并修改原数组
- 反转字符串
let x='abcde'
x.split('') //['a','b','c','d','e']
x.split('').reverse() // ['e','d','c','b','a']
x.split('').reverse().join('') //“edcba”
- join() 方法将一个数组(或一个类数组对象)的所有元素连接成一个字符串并返回这个字符串
- 自定义顺序
arr.sort() //会改变数组自身
let arr = [2,4,1,6,3]
arr.sort() //arr=[1,2,3,4,6]
arr.sort(function(a,b){ //arr.sort()的原理
if(a>b){
return 1
}else if(a===b){
return 0
}else{
return -1
}
})
arr.sort(function(a,b){ //返回arr[6,4,3,2,1]
if(a>b){
return -1
}else if(a===b){
return 0
}else{
return 1
}
})
- 如果数组的元素是对象呢?
let arr = [
{name:'小明',score:80},{name:'小红',score:90},{name:'小蓝',score:85}
]
arr.sort(function(a,b){
if(a.score > b.score){
return 1
}else if(a.score === b.score){
return 0
}else{
return -1
}
})
结果:
arr.sort(function}(a,b){........})的简易写法:
arr.sort((a,b)=>a-b) //数组元素为数字
arr.sort((a,b)=>a.score - b.score) //数组元素为对象,比较某个值
arr.sort((a,b)=>-(a.score - b.score)) //反向排序
7、查看数组中的元素
- 查看数组的属性名(更适用于对象,而不是数组,可以输出属性名不是顺序的属性名,如'x')
- for...in 适用于返回对象
Object.keys(arr) //方法一,更适用于对象
for (let key in arr){ //方法二,更适用于对象
console.log(`${key}:${arr[key]}`)
}
- 正确方法:
- 查看数字(字符串)属性名和值
for(let i=0;i<arr.length;i++){
console.log(`${i}: ${arr[i]}`)
}
示例:
- 数组自带的API,用于遍历数组
arr.forEach(function(item,index){ //item是数组的元素,index是数组的下标,可以是任意值
console.log(`${index}: ${item}`)
})
示例:
- 理解forEach
function forEach(array, fn){
for(let i=0;i<array.length;i++){
fn(array[i],i)
}
}
forEach(['a','b','c'], function(x){
console.log(x)
})
//输出a,b,c
function forEach(array, fn){
for(let i=0;i<array.length;i++){
fn(array[i],i)
}}
forEach(['a','b','c'], function(x,y){
console.log(x,y)
})
//输出 a 0;b 1;c 2
- forEach()方法的三个参数,x:数组元素,y:数组下标,z:整个数组
示例:
- forEach()方法与for循环的区别
- for是一个关键字,forEach()是一个方法
- for循环支持break和continue,forEach()不支持
- for循环是一个块级作用域,forEach()是一个函数作用域
- 查看单个属性
- 跟对象一样
let arr=[11,22,33]
arr[0] //11
- 索引越界
- 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
Cannot read property 'toString' of undefined意思是读取了undefined 的toString属性,不是toString是undefined, x.tostring() 其中x如果是undefined 就会报这个错
- 查找某个元素是否在数组里
arr.indexOf(item) //存在的话,返回数组下标,不存在返回-1
示例:
- 使用条件查找元素
arr.find(function(x){
return x%2===0 //如果x%2===0为true,则停止,返回并输出这个元素,但只会返回符合条件的第一个数
})
arr.findIndex(function(x){
return x%2===0 //返回对应元素的下标
})
示例:
8、数组变换
- map(不会改变原数组)
- n变n
- 示例:
let arr = [1,2,3,4,5,6]
arr.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) //返回[2,4,6]
- reduce(不会改变原数组)
- n变1
- 示例1
let arr = [1,2,3,4,5,6]
arr.reduce((sum,item) => {return sum+item},0) //返回21
- 示例2(reduce()代替map())`
let arr = [1,2,3,4,5,6]
arr.reduce((result,item) => {retrun result.concat(item*item)},[]) //[1,4,9,16,25,36]
- 示例3(reduce()代替filter())
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]
arr.reduce((result,item)=>result.concat(item%2 === 1?[]:item),[]) //简化版
9、面试题
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}
]
}
答案:
arr.reduce((result,item) =>{
if(item.parent === null){
result.id = item.id
result['名称'] = item['名称']
}else{
item.children = null
result.children.push(item)
delete item.parent
}
return result
},{id:null,children:[]})