数组在任何编程语言中都十分重要,作为最基础的数据结构,数组也常被用来实现其他的高级数据结构。比如,通过控制数组的存取方式来实现栈、优先队列等数据结构的特性。不同的编程语言对数组的创建、操作都各有不同。就我个人接触的语言中,JavaScript对于数组的定义是最为奇特的。其实用奇葩来形容也是可以的,跟其他语言来比可以这么来说。像Java编程语言中,定义一个数组,通常是要声明数组长度的。如果超过定义长度访问,会报OutOfBoundsException错误。一般称这样的数组声明是静态的,静态声明数组就是一开始就确定该数组占用的内存空间大小。在Java中数组中存放的数据类型也必需是一致的,不能有的字符有的数字。然而,在JavaScript的世界里,这些都变了。我们可以动态的改变某个数组的长度,并且不用管数组里存的数据类型,可以是数字、字符、对象混着来。这一切都变得毫无章法,这或许是脚本语言要体现的一个特点吧,不要太多条条框框束缚,让一切变得易操作。当然,不同语言各有利弊,关键看使用场景,不同场景对于编程语言的设计出发点都不同。下面就来好好谈谈JavaScript中的数组。

Javascript Array

数组的声明

在JavaScript中有两种声明方式,[]new Array()方式。第一种方式是通过数组字面量声明,这种声明方式比较简洁,推荐使用。第二种方式则是通过使用构造函数来声明,这种声明方式允许创建指定大小的数组。无论通过哪种方式声明数组,剩下的对数组的操作都是一样的。下面列出几个数组声明样例:

1
2
3
4
var array1 = [1, 2, 3];
var array2 = [1, "a", 2, "c"];
var array3 = new Array(4);
var array4 = new Array(3, 4, "a", "b");

上面声明了四个数组,接下来将通过操作这些数组来进行介绍。

JavaScript允许数组是稀疏的。什么是稀疏呢?比如,我们要在array1中直接插入一个索引为101的元素,不必管前100个元素是否存在,而且不管原来的数组长度是多少。只需要在对应位置赋值即可:array1[100] = 1,由于索引是从0开始,第101个的索引是100。这时候我们会疑惑,那前面没赋值的位置存的数据是什么,答案是undefined,正如我们访问超过数组长度的索引时,得到的也是undefined。JavaScript对未声明变量的获取得到的都是undefined,可以说现在array1中其实不存在索引为99的数据,但是array1的长度确实变成了101。

通常我们可能会看见这样的赋值:array1["a"] = "hello",这样的赋值并不是将元素添加到数组中,这种赋值应该是从Object继承而来的,其实Array也是对象,这样是对这个数组对象添加了一个叫a的属性,并给属性赋值为hello,这样并不会改变array1的数组长度。其实,通过for in循环来便利数组中的属性,可以发现在array1中属性包含了0、1、2、100、a。发现了前面的索引也在属性中,这与数组是对象的本质是符合的。而且数组比对象多了一个特性,就是length。如果对超过数组长度的索引K进行赋值,数组的长度将会变为K+1。如果对数组长度赋予小于当前数组长度的值L,则数组将会删除索引值大于或等于L的属性。如:array1.length = 1,得到的array1中的属性将为0、a。这样通过修改数组的length其实可以实现删除数组元素。

数组的操作

数组的操作主要是添加、删除、遍历等。前面也介绍了通过指定索引位置可以添加数组数据,当然这样做会导致数组稀疏,除非通过连续递增赋值。JavaScript提供了delete方法来删除指定元素,可以通过delete array[0]来删除索引为0的数组元素。但是,值得注意的是通过delete方法删除并不能改变数组的长度。delete方法的作用类似直接对delete的元素赋值undefined

当然,JavaScript提供了Array的一些内置函数,push()可以向数组末尾追加一个元素或一个数组,pop()可以从数组末尾删除一个元素。相对应的有unshift()shift(),与push()pop()不一样的是这两个元素操作的是数组的开头元素。unshift()往数组开头添加一个元素或数组,shift()往开头移除元素。

还有其他数组的操作,这里就不再详细介绍,下面截了个W3school的图。

JavaScript Array Methods

总结

通常在编程中都要用到数组,了解一个编程语言的数组是十分有用的。通过跟其他编程语言比较,我们会发现JavaScript的数组是比较奇特的,在使用时注意。