22·灵魂前端工程师养成-JavaScript数组

2022-09-26 17:19:15 浏览数 (1)

  • JS没有真正的数组
  • 创建一个数组
  • 数组中的元素增删改查

-曾老湿, 江湖人称曾老大。


-多年互联网运维工作经验,曾负责过大规模集群架构自动化运维管理工作。 -擅长Web集群架构与自动化运维,曾负责国内某大型金融公司运维工作。 -devops项目经理兼DBA。 -开发过一套自动化运维平台(功能如下): 1)整合了各个公有云API,自主创建云主机。 2)ELK自动化收集日志功能。 3)Saltstack自动化运维统一配置管理工具。 4)Git、Jenkins自动化代码上线及自动化测试平台。 5)堡垒机,连接Linux、Windows平台及日志审计。 6)SQL执行及审批流程。 7)慢查询日志分析web界面。


JS没有真正的数组


JS使用对象模拟数组

JS的数组不是典型的数组。

典型的数组:元素的数据类型相同,使用连续的内存存储,通过下标获取元素

JS的数组:元素的数据类型可以不同,内存不一定是连续的(对象是随机存储的),不能通过数字下标,而是通过字符串下标,这意味着数组可以有任何key。

比如:

代码语言:javascript复制
let arr = [1,2,3]
arr['xxx'] = 1

创建一个数组


创建数组

代码语言:javascript复制
let arr = [1,2,3]
let arr = new Array(1,2,3)
let arr = new Array(3)

转化的方式创建数组

代码语言:javascript复制
//将字符串转化为数组
let str = '1,2,3'

str.split(',')
(3) ["1", "2", "3"]

let str2 = '1,2,3,4'.split(',')

str2
(4) ["1", "2", "3", "4"]

let str3 = '123'.split('')

str3
(3) ["1", "2", "3"]

代码语言:javascript复制
//通过Array.from将不是数组的元素 变成数组(但是很局限)
Array.from('1234')
(4) ["1", "2", "3", "4"]

Array.from(123)
[]

Array.from(true)
[]

Array.from({name: 'zls'})
[]

Array.from({0:'a',1:'b',2:'c'})
[]

//对象必须有0 1 2 3的下标,然后有length
Array.from({0:'a',1:'b',2:'c',length:3})
(3) ["a", "b", "c"]


伪数组

代码语言:javascript复制
array = [1,2,3,4,5] // new Array(1,2,3,4,5)
(5) [1, 2, 3, 4, 5]

array.__proto__ === Array.prototype
true

array
(5) [1, 2, 3, 4, 5]
0: 1
1: 2
2: 3
3: 4
4: 5
length: 5
__proto__: Array(0)


array2 = {0:'a',1:'b',2:'c',3:'d'}
{0: "a", 1: "b", 2: "c", 3: "d"}

array2.__proto__ === Array.prototype
false

注意: 在伪数组的原型链中,并没有数组的原型,它的原型是对象(Object)的原型

我们使用 document.querySelectorAll('div') 就是一个伪数组

代码语言:javascript复制
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>

<body>
  <div>1</div>
  <div>2</div>
  <div>3</div>
</body>

</html>
代码语言:javascript复制
let divList =  document.querySelectorAll('div')
console.log(divList)

当你使用divList.push(4)的时候,会发现报错,根本没有办法使用数组的push

如果我们想要他变成数组,就要使用刚才所学 Array.from

代码语言:javascript复制
let divList =  document.querySelectorAll('div')
let divArray = Array.from(divList)
console.log(divArray)

没有数组共用属性的数组,就是伪数组


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

代码语言:javascript复制
//使数组变长(合并)

array1 = [1,2,3]
(3) [1, 2, 3]

array2 = [2,3,4]
(3) [2, 3, 4]

array1.concat(array2)
(6) [1, 2, 3, 2, 3, 4]

array1
(3) [1, 2, 3]

array2
(3) [2, 3, 4]

代码语言:javascript复制
// 使数组变短(截取)
array3 = [1,2,3,4,5,6,7,8]
(8) [1, 2, 3, 4, 5, 6, 7, 8]

array4 = array3.slice(2)
(6) [3, 4, 5, 6, 7, 8]

array4
(6) [3, 4, 5, 6, 7, 8]

数组中的元素增删改查


删除元素

代码语言:javascript复制
let arr = ['a','b','c']

delete arr['0']

// 很惊奇的事情发生了,数组的长度不变

let arr =  ['a','b','c','d']

arr.length
4

delete arr['0']
true

arr.length
4

arr
(4) [empty, "b", "c", "d"]

只有长度,没有下标的 数组,叫做:稀疏数组

如果修改长度,,,属性名就没有了

代码语言:javascript复制
let arr =  ['a','b','c','d']

arr.length = 2
2

arr
(2) ["a", "b"]

注意: JS千万不要改length

所以,删除数组使用shift 或者 pop

代码语言:javascript复制
let array = [1,2,3,4,5]

//从左边删除
array.shift()
1

array
(4) [2, 3, 4, 5]

array.shift()
2

array
(3) [3, 4, 5]

//从后面删除
array.pop()
5

array
(2) [3, 4]

//从中间删除,从下标为2的地方删除一个元素
let array1 = [1,2,3,4,5]

array1.splice(2,1)
[3]

array1
(4) [1, 2, 4, 5]

//在删除的同时还可以增加
let array2 = [1,2,3,4,5]

array2.splice(2,1,666)
[3]

array2
(5) [1, 2, 666, 4, 5]

array2.splice(2,1,777,888,999)
[666]

array2
(7) [1, 2, 777, 888, 999, 4, 5]


遍历元素

代码语言:javascript复制
let arr = [1,2,3,4,5]

arr.x = 'x'
"x"

Object.keys(arr)
(6) ["0", "1", "2", "3", "4", "x"]


//查看数组的value,下面几种方法都是有问题的
arr
(5) [1, 2, 3, 4, 5, x: "x"]

// 为什么带个x?
Object.values(arr)
(6) [1, 2, 3, 4, 5, "x"]


// 为什么带个x?
for(let i in arr){
    console.log(i)
}
VM617:2 0
VM617:2 1
VM617:2 2
VM617:2 3
VM617:2 4
VM617:2 x

//正确方式,看到所有的key
for(let i=0;i<arr.length;i  ){
    console.log(i)
}
0
1
2
3
4

//看到所有的key和value
for(let i=0;i<arr.length;i  ){
    console.log(i,arr[i])
}
0 1
1 2
2 3
3 4
4 5


for(let i=0;i<arr.length;i  ){
    console.log(`${i}:${arr[i]}`)
}
0:1
1:2
2:3
3:4
4:5

//使用forEach函数遍历数组
arr.forEach( function(xxx){
  console.log(xxx)
} )
1
2
3
4
5

arr.forEach( function(xxx,yyy){
  console.log(xxx,yyy)
} )
1 0
2 1
3 2
4 3
5 4

arr.forEach( function(xxx,yyy){
  console.log(`${xxx}:${yyy}`)
} )
1:0
2:1
3:2
4:3
5:4

//使用map函数遍历数组
arr.map( function(xxx,yyy){
  console.log(xxx,yyy)
} )
1 0
2 1
3 2
4 3
5 4

查看单个元素

代码语言:javascript复制
let arr = [1,2,3,4,5,6,7]

arr[1]
2

arr[0]
1

//越界索引
for(let i=0;i<=arr.length;i  ){
    console.log(arr[i].toString())
}
1
2
3
4
5
6
7
Uncaught TypeError: Cannot read property 'toString' of undefined
    at <anonymous>:2:24

读取了undefined的toString属性

代码语言:javascript复制
//查找某个元素是否在数组中
let arr = [1,23,45,33,16,66,88]

arr.indexOf(1)
0

arr.indexOf(88)
6

//找某个元素是不是偶数,或者是5的倍数
let arr = [12,23,12,222,45,16,100]

arr.find((x)=> x%5 === 0)
45

arr.find(function(x){ return x%5 === 0 })
45

arr.find(function(x){ return x%2 === 0 })
12


//找到下标
arr.findIndex(function(x){ return x%2 === 0 })
0

给数组增加元素

错误添加元素方式

代码语言:javascript复制
//从下面我们会发现,如果突然写个很大的下标,数组长度会变成101,空元素有很多,这样就变成了一个稀疏数组
let arr2 = [1,2,3,4,5,7,8,9,4,5,6,7]

arr2[12] = 22
22

arr2
(13) [1, 2, 3, 4, 5, 7, 8, 9, 4, 5, 6, 7, 22]

arr2.length
13

arr2[13] = 33
33

arr2
(14) [1, 2, 3, 4, 5, 7, 8, 9, 4, 5, 6, 7, 22, 33]

arr2.length
14

arr2[100] = 666
666

arr2
(101) [1, 2, 3, 4, 5, 7, 8, 9, 4, 5, 6, 7, 22, 33, empty × 86, 666]

arr2.length
101

推荐方式

代码语言:javascript复制
//push在最后面添加元素
let arr = [1,2,3,4,5,6]

arr.push(7)
7

arr
(7) [1, 2, 3, 4, 5, 6, 7]

arr.push('a','b','c')
10

arr
(10) [1, 2, 3, 4, 5, 6, 7, "a", "b", "c"]

//unshift在最前面添加元素
arr.unshift(0)
11

arr
(11) [0, 1, 2, 3, 4, 5, 6, 7, "a", "b", "c"]

arr.unshift('x','y','z')
14

arr
(14) ["x", "y", "z", 0, 1, 2, 3, 4, 5, 6, 7, "a", "b", "c"]

//在指定位置添加
arr
(14) ["x", "y", "z", 0, 1, 2, 3, 4, 5, 6, 7, "a", "b", "c"]

arr.splice(9,0,6.5) //在下标是9的位置,删除0个元素,添加一个元素为6.5
[]

arr
(15) ["x", "y", "z", 0, 1, 2, 3, 4, 5, 6.5, 6, 7, "a", "b", "c"]


修改数组元素

代码语言:javascript复制
//方法一:还是使用splice
arr.splice(9,1,6.666)
[6.5]

arr
(15) ["x", "y", "z", 0, 1, 2, 3, 4, 5, 6.666, 6, 7, "a", "b", "c"]

//方法二:直接修改
arr[9] = 8.888
8.888

arr
(15) ["x", "y", "z", 0, 1, 2, 3, 4, 5, 8.888, 6, 7, "a", "b", "c"]

//数组反转
arr.reverse()
(15) ["c", "b", "a", 7, 6, 8.888, 5, 4, 3, 2, 1, 0, "z", "y", "x"]

arr
(15) ["c", "b", "a", 7, 6, 8.888, 5, 4, 3, 2, 1, 0, "z", "y", "x"]

//面试题,如何把字符串反转?

let str = 'abcd'

str.split('')
(4) ["a", "b", "c", "d"]

str.split('').reverse()
(4) ["d", "c", "b", "a"]

str.split('').reverse().join('')
"dcba"

//顺序是乱的数组,变成有序数组
let arr = [5,2,1,3,4]

arr.sort()
(5) [1, 2, 3, 4, 5]

arr
(5) [1, 2, 3, 4, 5]

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

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

//如果是下面的数组,JS根本就不知道,按照什么排序
let stu = [
    {name: 'zhang3',score: 99},{name: 'li4',score: 95},{name: 'wang5',score: 100}]
    
stu.sort()
(3) [{…}, {…}, {…}]
0: {name: "zhang3", score: 99}
1: {name: "li4", score: 95}
2: {name: "wang5", score: 100}


//所以我们需要通过sort的函数,来告诉JS用score排序
stu.sort(function(a,b){
  if(a.score > b.score){
    return 1
  }else if(a.score === b.score){
    return 0
  }else{
    return -1
  }
})
(3) [{…}, {…}, {…}]
0: {name: "li4", score: 95}
1: {name: "zhang3", score: 99}
2: {name: "wang5", score: 100}

//简便写法

stu.sort((a,b) => a.score - b.score)

(3) [{…}, {…}, {…}]
0: {name: "li4", score: 95}
1: {name: "zhang3", score: 99}
2: {name: "wang5", score: 100}

数组变换

代码语言:javascript复制
//map: n变n
let arr = [1,2,3,4,5,6]

arr.map(item => item * item)
(6) [1, 4, 9, 16, 25, 36]

//filter: n变少
arr
(6) [1, 2, 3, 4, 5, 6]

arr.filter(item => item%2 === 0 ?true :false)
(3) [2, 4, 6]

arr.filter(item => item%2 === 0)
(3) [2, 4, 6]

//reduce:n变1,抢劫...
for(let i=0;i<arr.length;i  ){
    //sum = sum   arr[i] 可以简写
    sum  = arr[i]
}
21

arr.reduce((sum,item)=>{return sum item},0)
21

//使用reduce实现,map的例子
arr.reduce((result,item) => {return result.concat(item * item)},[])
(6) [1, 4, 9, 16, 25, 36]

//使用reduce实现,filter的例子
arr.reduce((result,item) => {
  if(item % 2 === 1){
    return result
  } else{
    return result.concat(item)
  }
},[])
(3) [2, 4, 6]

//简化代码
arr.reduce((result,item) => item % 2 === 1 ?result :result.concat(item),[])
(3) [2, 4, 6]

//有经验的前端简化代码
arr.reduce((result,item) => result.concat(item % 2 === 1 ?[] :item),[])
(3) [2, 4, 6]

面试题:数据变换

代码语言:javascript复制
//将下列数组
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}
  ]
}

代码语言:javascript复制
arr.reduce((result,item) => {
  result[item.id] = item
  return result
},{})

{1: {…}, 2: {…}, 3: {…}}
1: {2: {…}, 名称: "动物", id: 1, parent: null}
2: {3: {…}, 名称: "狗", id: 2, parent: 1}
3: {名称: "猫", id: 3, parent: 1}

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: []})

0 人点赞