好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

JavaScript 数组

JavaScript 数组

数组是一种使用整数作为键 (integer-key-ed) 属性 和长度 (length) 属性 之间关联的常规对象。此外,数组对象还继承了 Array.prototype 的一些操作数组的便捷 方法 。——MDN

数组可以存放多个值。数组的 数 不是指数字,而是指 数据 ,数组可以存放任意数据类型的值。

从理论上讲,在内存允许的情况下,数组的长度是无限的。

1. 创建数组

数组由中括号 [] 包裹,每一项之间用逗号 , 分隔。

  [ 第一项 ,  第二项 ,  第三项 ,   ...   ,  第n项 ] 
 

创建数组最常见的方式是使用字面量。

  var  hobby  =   [  'java'  ,   'c'  ,   'c++'  ,   'python'  ,   'javascript'  ,   ,   ,   ,   true  ,   false  ]  ; 

console .  log  ( hobby )  ; 
 

通过直接描述 一个 数组的方式就可以创建 一个 数组。

2. 数组长度

数组的长度可以通过 length 属性 获取 。

  var  arr  =   [  ,   ,   ,   ,   ]  ; 

console .  log  ( arr . length )  ;   // 5 
 

3. 访问数组成员

数组的每一项可以称之为 成员 。

数组成员可以通过 下标 访问,下标也可以称为 索引 。

下标可以理解成数组成员的编号,编号从 0 开始,到数组长度 -1 。

  var  arr  =   [  '第一项'  ,   '第二项'  ,   '第三项'  ]  ; 

 var  item1  =  arr [  ]  ;   // 从0开始编号 第一项的下标是0 
 var  item2  =  arr [  ]  ; 
 var  item3  =  arr [  ]  ; 

console .  log  ( item1 )  ;   //  输出 :第一项 
console .  log  ( item2 )  ;   //  输出 :第二项 
console .  log  ( item3 )  ;   //  输出 :第三项 
 

通过 数组[下标] 的方式即可访问到成员。

4. 遍历数组

数组遍历主要有两种方式:

for 循环 forEach 方法

4.1 for 循环

使用 for 循环,从数组下标 0 循环到最后一位,过程中通过下标访问成员。

  var  arr  =   [  '第一项'  ,   '第二项'  ,   '第三项'  ,   '第四项'  ,   '第五项'  ]  ; 

 var  i ,  len ; 
 for   ( i  =   ,  len  =  arr . length  -   ;  i  <=  len ;  i ++  )   { 
  console .  log  ( arr [ i ]  )  ; 
 } 
 

@H_334_ 404 @4.2 forEach 方法

forEach 是数组原型上的 方法 ,所有数组都具有此 方法 。

forEach 接收 一个 函数 作为参数,在遍历每一项的时候,这个 函数 会被 调用 ,同时将当前遍历到的项、当前项的下标(索引)、遍历的数组作为 函数 参数传递过来。

  var  arr  =   [  '第一项'  ,   '第二项'  ,   '第三项'  ,   '第四项'  ,   '第五项'  ]  ; 

arr .  forEach  (  function  ( item ,  index ,  arr )   { 
  console .  log  (  '第'   +   ( index  +   )   +   '项的值是:'   +  item )  ; 
 }  )  ; 
 

第二个参数的值也是从 0 开始的。

通常第三个参数用到的比较少,没有用到可以没必要接收这个参数。

5. 修改 数组成员的值

成员的值可以通过 数组[下标] = 值 的方式进行 修改 。

  var  arr  =   [  '一'  ,   '三'  ,   '三'  ,   '四'  ]  ; 

console .  log  ( arr [  ]  )  ;   //  输出 :"三" 

arr [  ]   =   '二'  ; 

console .  log  ( arr [  ]  )  ;   //  输出 :"二" 
 

6. 增减数组项

数组提供了很多方式来对成员进行增减操作,也可以依靠其他特性来 增加 减少数组成员。

6.1 增加

6.1.1 直接给指定位置赋值

通过下标,直接访问到 一个 不存在的成员,然后进行赋值,就可以为数组 增加 一项。

  var  arr  =   [  'jquery'  ,   'react'  ]  ; 

arr [  ]   =   'vue'  ; 
arr [  ]   =   'angular'  ; 

console .  log  ( arr [  ]  )  ;   //  输出 :"angular" 
console .  log  ( arr . length )  ;   //  输出 :3 
 

6.1.2 push 方法

push 方法 接收任意个参数,这些参数会依次 添加 到数组的末尾, 添加 完后返回数组新的长度。

  var  arr  =   [  ]  ; 

 var  length  =  arr .  push  (  ,   )  ; 

console .  log  ( arr )  ;   //  输出 :[1, 2, 3] 
console .  log  ( length )  ;   //  输出 :3 
 

通常不会用到这个返回的长度,可以不需要接收返回值。

6.1.3 unshift 方法

unshift 接收任意个参数,这些参数会被 添加 到数组头部, 添加 完后返回数组新的长度。

  var  arr  =   [  ]  ; 

 var  length  =  arr .  unshift  (  ,   )  ; 

console .  log  ( arr )  ;   //  输出 :[1, 2, 3] 
console .  log  ( length )  ;   //  输出 :3 
 

6.2 删除

6.2.1 pop 方法

pop 方法 会 删除 数组最后一项,并将 删除 项作为返回值。

  var  arr  =   [  'c++'  ,   'java'  ,   'javascript'  ]  ; 

 var  lastOne  =  arr .  pop  (  )  ; 

console .  log  ( lastOne )  ;   //  输出 :"javascript" 
 

如果数组是空的, 调用 pop 会返回 undefined 。

@H_ 419 _886@6.2.2 shift 方法

shift 方法 会 删除 数组的第一项,并将 删除 项作为返回值。

  var  arr  =   [  '996'  ,   '007'  ]  ; 

 const  f irs t  =  arr .  shift  (  )  ; 

console .  log  ( f irs t )  ;   //  输出 :"996" 
 

与 pop 一样,如果是数组为空的情况下,会返回 undefined 。

6.3 在数组中间 删除 或 添加 值

splice 方法 可以在任意位置 添加 或 删除 值。

这个 方法 接受任意个参数,前两个为从哪里开始(从 0 开始计数), 删除 几个,从第三个开始则是要 添加 的项。

 arr .  splice  ( 从第几个开始 ,  要 删除 几个 ,  要 添加 的项目 ,  要 添加 的项目 ,   ...  ,  要 添加 的项目n )  ; 
 

如果不需要 删除 ,只需要往数组中间插入值,只需要传递 0 给第二个参数即可。

  // 在第二项之后插入3, 4, 5 
 var  arr  =   [  ,   ,   ]  ; 

arr .  splice  (  ,   ,   ,   ,   )  ; 
 

因为第 一个 参数是从 0 开始计数,所以在第二项之后,就是要插入在第三项的位置,所以传递 2 ,不需要 删除 项目,所以第二个参数传递 0 ,之后就是要插入的项。

注意:往数组中间插入数据的情况相对较少,数组做这种操作是比较低效的,小量的操作对 性能 的影响可以忽略不计,但有超大量非首尾的增减操作,应考虑使用 链表 。

删除 项只需要指定从第几项开始 删除 ,要 删除 几项即可。

  //  去除  '996'、'加班' 
 var  arr  =   [  '早睡早起'  ,   '朝九晚五'  ,   '996'  ,   '加班'  ]  ; 

arr .  splice  (  ,   )  ; 
 

'996’和’加班’是连续的,所以 一个 splice 就可以 删除 掉这 2 项,2 个参数的意思就是从第 2 项开始, 删除 2 项。

7. 清空数组

将数组所有成员全部 删除 就达到了清空的 效果 。

  var  arr  =   [  ,   ,   ,   ]  ; 

arr .  splice  (  ,  arr . length )  ; 
 

当然也可以使用 pop 一个 个 删除 ,但是通常都不会用这种方式。

清空数组最常用的方式是重新给变量赋值。

  var  arr  =   [  'red'  ,   'green'  ,   'blur'  ]  ; 

arr  =   [  ]  ; 

console .  log  ( arr )  ;   //  输出 空数组:[] 
 

通过给变量赋值 一个 新的空数组,达到清空数组的目的,但是这样会改变引用,新赋值的数组和之前的数组并不是同 一个 。

另一种方式可以让保持对当前数组的引用。

  var  arr  =   [  'yellow'  ,   'black'  ]  ; 

arr . length  =   ; 
 

通过给数组的 length 属性 重新赋值,也可以达到清空数组的 效果 。

这种方式相对灵活,假如需求是保留三项、五项,只需要给 length 赋值对应的值即可。

8. 使用 Array 创建数组

内建对象 Array 也可以用来创建数组。

  var  arr  =   new   Array  (  )  ; 
 

如果什么参数都不传递,则返回 一个 空数组。

传参则有 2 种情况:

如果只传 一个 参数,并且这个参数的类型为数字,则会创建长度为这个数字的数组; 传入其他类型的 一个 或者多个参数,则会将这些参数组合成数组。

  var  arr  =   new   Array  (  )  ; 

console .  log  ( arr )  ;   //  输出 :[empty × 10] 
console .  log  ( arr . length )  ;   //  输出 :10 
 

在控制台可以观察到这个数组长度为 10,但均为 empty 。

如果尝试着访问其中某一项,得到的值是 undefined 。

  var  arr1  =   new   Array  (  'item1'  )  ; 

 var  arr2  =   new   Array  (  ,   ,   'item3'  )  ; 

console .  log  ( arr1 )  ;   //  输出 :["item1"] 
console .  log  ( arr2 )  ;   //  输出 :[1, 2, "item3"] 
 

这样创建的数组,成员与传参一致。

9. 数组中的 undefined 与 empty

在数组中 undefined 与 empty 是有区别的。

使数组项变成 empty 通常有两种方式。

使用 Array 对象同时提供了长度创建出来的数组 使用 delete 关键字 删除 的数组项

  var  arr1  =   new   Array  (  )  ; 

arr1 [  ]   =   ; 

 var  arr2  =   [  ,   ,   ,   ,   ]  ; 

 delete  arr2 [  ]  ; 

console .  log  ( arr1 )  ; 
console .  log  ( arr2 )  ; 
 

虽然 empty 的项在访问的时候返回的是 undefined ,但其本身只做简单占位,\ 是遍历不到的。

  var  arr  =   [  ,  undefined ,   ,   ,   ]  ; 

 delete  arr [  ]  ; 

arr .  forEach  (  function  ( item ,  index )   { 
  console .  log  ( index ,  item )  ; 
 }  )  ; 

 var  i  =   ; 
 for   ( i  in  arr )   { 
  console .  log  ( i ,  arr [ i ]  )  ; 
 } 
 

上面两种遍历的方式都是遍历不到 empty 项的,而 undefined 是可以遍历到的,这是最主要的区别。

10. 使用数组

数组非常常用,大量的 HTML 字符串在做拼接的时候,就会使用到数组。

除了用于简单的存储数据,数组也可以被用来 解决 问题。

10.1 判断括号是否匹配

判断 一个 数学式子的括号匹配是否合法,如 (1 + 2) * (3 + 4)) ,这个式子就是不合法的。

校验括号合法不单单要看左括号和右括号的 数量 是否相等,还要看括号的顺序, ))(( 这样的括号顺序一定是 错误 的。

利用 JavaScript 数组的特性,可以很容易的实现。

  // 空数组 
 var  stack  =   [  ]  ; 

 //  一个 式子 
 var  equation  =   '(1 + (2 - 3) * 4) / (1 - 3)'  ; 

 var  i ,  len ; 
 for   ( i  =   ,  len  =  equation . length ;  i  <  len ;  i ++  )   { 
   if   ( equation [ i ]   ===   '('  )   {   // 如果碰到左括号 
     // 往数组里放个1 
    stack .  push  (  )  ; 
   }   else   if   ( equation [ i ]   ===   ')'  )   {   // 如果碰到右括号 
     if   (  ! stack . length )   {   // 判断数组长度,如果是0,则肯定是出错的,数组长度0的时候说明没有左括号,没有左括号是不可能出现右括号的 
       // 随便放 一个 1 
      stack .  push  (  )  ; 
       break  ; 
     } 
     // 如果数组不是空的 就从数组末尾拿 一个 走。 
    stack .  pop  (  )  ; 
   } 
 } 

 // 判断数组长度 
 if   (  ! stack . length )   {   // 如果数组已经空了,说明括号都一一对应,式子里的括号没问题。 
  console .  log  (  '括号合法'  )  ; 
 }   else   { 
  console .  log  (  '括号不合法'  )  ; 
 } 
 

使用数组实现的具体思路就是,碰到左括号就往数组里放 一个 成员,碰到 一个 右括号就拿掉 一个 成员。

这样如果最后有剩下,说明括号没有一一成对。

(1+2*(3+4))*1 如这样 一个 式子:

 初始化操作:
  定义数组 arr为空

从式子第 一个 字符开始循环
  第一次循环:
    数组的值为 []
    得到字符"("
    判断是左括号,往数组里放 一个 1,表示碰到了左括号

  第二次循环
    数组的值为 [1]
    得到字符"+"
    既不是左括号,又不是右括号,进行下一轮循环,不做操作

  第三次循环
  第四次循环
  第五次循环
    与第二次循环基本一致

  第六次循环
    数组的值为 [1]
    得到字符"("
    是左括号 往数组里再放 一个 1,表示碰到了左括号

  第七次循环
    数组值为 [1, 1]
    得到字符"3"
    不是左括号,也不是右括号,进行下一轮循环

  第八次循环
  第九次循环
    与第七次一致

  第十次循环
    数组的值为 [1, 1]
    得到字符")"
    是右括号,从数组末尾拿掉一项

  第十一次循环
    数组的值为 [1]
    得到字符")"
    是右括号,从数组末尾拿掉一项

  第十二次循环
  第十三次循环
    数组值为 []
    都不是括号,不做操作
循环结束

判断数组值,如果是空的,说明括号匹配完了,显然 (1+2*(3+4))*1 是合法的
 

当然这种判断有局限性,假如碰到 ((1+)2)-3 这种非括号造成不合法的式子,就判断不出来了。

其实这里用到了 栈 这种数据结构,这个问题在栈的应用上很经典,是算法入门常见面试题之一。

11. 类数组

类数组并不是数组,而是长得像数组的对象。

  var  fakeArray  =   { 
   :   '第一项'  , 
   :   '第二项'  , 
   :   '第三项'  , 
  length :   , 
 }  ; 

console .  log  ( fakeArray [  ]  )  ;   //  输出 :"第一项" 
console .  log  ( fakeArray . length )  ;   //  输出 :3 
 

上述例子中的 fakeArray 就是 一个 类数组, 属性 是以类型数组的 下标 的形式存在,同时也具有 length 属性 。

这种类数组对象,也被称为 array-like对象 ,部分文献也称为 伪数组 。

类数组对象可以转化为数组,许多 方法 在设计时也会考虑 支持 类数组。

12. 小结

JavaScript 中的数组非常灵活,可以存放任意类型、任意长度 (内存足够的情况下) 的数据,其下标从 0 开始,最大到数组长度减去 1 ,并提供了一系列 方法 ,来完成增、删、改、查操作。

数组项的 empty 和 undefined 的区别,是面试中常问的问题。

JavaScript switch 语句 ? ?JavaScript 数字

查看更多关于JavaScript 数组的详细内容...

  阅读:54次

上一篇

下一篇

第1节:什么是 JavaScript    第2节:学习环境准备    第3节:调试方案    第4节:JavaScript 变量    第5节:JavaScript 数据类型    第6节:JavaScript if 语句    第7节:for 语句    第8节:JavaScript 算数运算符    第9节:JavaScript 比较运算符    第10节:JavaScript 逻辑运算符    第11节:JavaScript 函数    第12节:JavaScript 表达式    第13节:JavaScript 对象    第14节:JavaScript 字符串    第15节:JavaScript 数字    第16节:JavaScript 数组    第17节:JavaScript switch 语句    第18节:JavaScript while 语句    第19节:JavaScript 的 break 与 continue    第20节:JavaScript with    第21节:document.cookie    第22节:JavaScript Function    第23节:JavaScript Math    第24节:JavaScript Date    第25节:JavaScript RegExp    第26节:JavaScript JSON    第27节:什么是 DOM    第28节:DOM 和 JavaScript 的关系    第29节:获取和操作 DOM 节点    第30节:DOM 与事件    第31节:DOM 事件绑定    第32节:DOM 事件对象    第33节:DOM 事件流    第34节:事件相关的优化    第35节:自定义事件    第36节:表单校验    第37节:什么是 BOM    第38节:常用的 BOM 相关对象    第39节:BOM 常用属性和方法    第40节:AJAX    第41节:异常处理    第42节:三元运算符    第43节:逗号操作符    第44节:void    第45节:typeof    第46节:delete 操作符    第47节:debugger    第48节:getter & setter    第49节:new 运算符与构造函数    第50节:JavaScript 原型    第51节:JavaScript instanceof    第52节:JavaScript this    第53节:严格模式    第54节:作用域    第55节:闭包    第56节:变量提升    第57节:对象包装器    第58节:Lodash    第59节:moment    第60节:swiper    第61节:ECMAScript 6    第62节:Node.js    第63节:Babel    第64节:CSS 预处理器    第65节:代码规范    第66节:TypeScript    第67节:WebComponents    第68节:Vue、React、Angular    第69节:小程序    第70节:JavaScript 关键字    第71节:分号导致的问题    第72节:对象属性访问问题    第73节:this 使用问题    第74节:浮点数精度问题    第75节:独一无二的 NaN    第76节:避免全局污染    第77节:控制台观察对象问题    第78节:根据环境选择语言特性    第79节:相关资源