JavaScript中的数组

参考书籍:《JavaScript高级程序设计(第3版)》

        作为一种可以说是最常用的类型,EMCAScript当中的数组与其他语言的数组有很大区别,例如数组元素可以是不同类型,数组长度可以动态调整等,因此我总结了一下EMCAScript中的数组类型,即 $Array$ 类型(主要集中于与其他语言不同的地方)。

  1. 数组创建
  2. 数组长度
  3. 数组方法
    1. 判定方法
    2. 转换方法
    3. 栈方法
    4. 队列方法
    5. 排序方法
    6. 操作方法
    7. 位置方法
    8. 迭代方法
    9. 归并方法

1. 数组创建

        EMCAScript中数组是一个特殊的类型,有自己的构造函数,我们可以通过 $new$ 运算符来调用数组的构造函数。

var array = new Array(); //建立一个空数组

        当然,你也可以通过传参来调用带参构造函数。

var array1 = new Array(10); //大小为10的数组
var array2 = new Array(1, 2, 3); //包含1,2,3三个元素的数组
var array2 = new Array("A"); //包含一个"A"的数组

        但是在这里要注意的是,如果你只给构造函数传一个数字,则会创建对应大小的数组,其中每一项的值都是 $undefined$ ;如果传的是多个数字,则会创建包含这些数字的数组。
        除了调用构造函数之外,我们还可以使用字面量语法。如下所示:

var array1 = []; //空数组
var array2 = [1]; //包含一个1的数组
var array3 = ["A", "B", "C"]; //包含三个元素的数组

2. 数组长度

        与其他语言相似,EMCAScript中的数组下标从 $0$ 开始, $length - 1$ 结束,要访问对应下标的值,可以通过方括号内添加下标读取或者写入数据,如下所示:

var array = ["A", "B", "C"];
console.log(array[0]); // "A"
array[0] = "D";
console.log(array[0]); // "D"

        但是与其他语言不同的是,如果你访问的下标超过了当前数组的长度,即 $length - 1$ ,会返回 $undefined$。而你在这时写入数据的话,数组的长度会更新为你访问的下标值加一,而从原先的最大下标到新的最大下标之间的值会以 $undefined$ 填充。如下所示:

var array = ["A", "B", "C"];
console.log(array[5]); //undefined
array[5] = "F";
console.log(array[4]); //undefined
console.log(array[5]); //"F"

        EMCAScript中的数组长度还有个特点,就是它不是只读的,你可以通过设置数组长度的值直接改变数组大小,这时新增的值会以 $undefined$ 填充。如下所示:

var array = ["A", "B", "C"];
array.length = 2;
console.log(array[2]); //undefined
array.length = 4;
console.log(array[2]); //undefined

3. 数组方法

        EMCAScript中的数组方法非常有特点,它使得JavaScript中的数组可以代替多种结构。


3.1 判定方法

        由于JavaScript是一门弱类型语言,因此如何判断一个对象为数组非常有用的,对于一个网页或者全局作用域,使用 $instanceof$ 操作符即可。如下所示:

var array = [];
console.log(array instanceof Array); //true

        但问题在于,如果存在多个框架,即多个全局作用域,这时如果你从另一个框架传入数组,由于各个框架中的数组分别有各自的构造函数,因此这时对另一个框架中的数组使用 $instanceof$ 操作符时会返回 $false$ 。
        为了避免这种情况,可以使用EMCAScript5中的 $Array.isArray(\ )$ 方法,该方法不会受到作用域影响,如下所示:

var array = [];
console.log(Array.isArray(array)); //true

        当然要注意的是,可能有的浏览器不支持该方法。


3.2 转换方法

        EMCAScript中所有的对象都具有三个方法—— $toLocaleString(\ )$ 、$toString(\ )$ 以及 $valueOf(\ )$ 方法。其中 $valueOf(\ )$ 方法返回数组本身;$toString(\ )$ 方法以字符串的形式返回数组中的所有元素(每个元素之间用逗号隔开);$toLocaleString(\ )$ 大部分情况下与 $toString(\ )$ 返回相同的值,但是不同之处在于 $toLocaleString(\ )$ 方法是调用每个元素的 $toLocaleString(\ )$ 方法后再用逗号连接起来,也就是说当一个元素的 $toString(\ )$ 方法与它的 $toLocaleString(\ )$ 方法不同时,调用数组的 $toString(\ )$ 方法和 $toLocaleString(\ )$ 方法就会返回不同的值。

var object = {
    toLocaleString: function() {
        return "LocaleString";
    },
    toString: function() {
        return "String";
    }
};
var array = [1, object];
console.log(array.toString()); //"1,String"
console.log(array.toLocaleString()); //"1,LocaleString"

3.3 栈方法

        通过EMCAScript中数组的栈方法,我们可以把一个数组当成栈来使用。实现栈的两个方法分别是 $Array.prototype.push(\ )$ 和 $Array.prototype.pop(\ )$ 。$Array.prototype.push(\ )$ 方法接收一个或多个参数,将这些参数按序压入栈内,返回参数个数;$Array.prototype.pop(\ )$ 方法推出栈顶元素并返回。

var stack = [];
console.log(stack.push(1, 2)); // 2
console.log(stack.pop()); // 2
console.log(stack.length); // 1

3.4 队列方法

        类似于栈方法,EMCAScript中也提供了能够让一个数组当作队列使用的方法。由于 $Array.prototype.push(\ )$ 方法本身就是向末尾添加元素的方法,因此只需要另一个从数组开始删除元素的方法即可,实现这一操作的方法就是 $Array.prototype.shift(\ )$ 方法,它能够删除并返回数组第一项元素。此外,EMCAScript还提供了一 $Array.prototype.unshift(\ )$ ,即向数组开始添加元素并返回元素个数。通过结合 $Array.prototype.push(\ )$ , $Array.prototype.pop(\ )$ , $Array.prototype.shift(\ )$ , $Array.prototype.unshift(\ )$ 这四个方法,我们能够把一个数组当作双向队列使用。

var array = [];
console.log(array.unshift(3, 2)); // 2
console.log(array.shift()); // 3

3.5 排序方法

        EMCAScript中提供了两个数组排序方法—— $Array.prototype.reverse(\ )$ 和 $Array.prototype.sort(\ )$ ,分别用于数组反转和排序。需要注意的是,在不传参数的情况下 $Array.prototype.sort(\ )$ 方法默认会调用每个元素的 $toString(\ )$ 方法,之后通过字符串比较来确定大小,得到升序数组。而通过传参,我们可以得到想要的排序数组,具体的传入参数应该是一个函数对象,类似于C++Java中的排序方法,该函数接收两个元素,若前者需要排在后者前面,则应返回一个负数,若前者等于后者,则返回 $0$ ,若前者需要排在后者后面,则返回一个正数。如下所示:

var array = [1, 3, 4, 5, 6];
array.sort(function(value1, value2) {
    return value2 - value1;
});
console.log(array); // "6,5,4,3,1"

3.6 操作方法

        EMCAScript提供了很多操作方法,这里选择了几个常用方法。

var array = [1, 2, 3];
console.log(array.concat([4, 5], 6, 7)); // "1,2,3,4,5,6,7"
console.log(array.slice(1, 2)); // "2"
console.log(array.splice(1, 2, 3, 4, 5)); // "2,3"
console.log(array); // "1,3,4,5"

3.7 位置方法

        类似于JavaEMCAScript提供了 $Array.indexOf(\ )$ 方法和 $Array.lastIndexOf(\ )$ 。且其用法也与Java相似,传入要查找的元素,返回其位置,若未找到,返回 $-1$ 。

console.log([1, 2, 3].lastIndexOf(2)); // 1

3.8 迭代方法

        迭代方法,即遍历数组,对每个元素执行某个指定操作的函数。EMCAScript中提供了五个迭代方法,每个方法都接收一个或两个参数,第一个参数指定要进行操作的函数,第二个参数(可选)指定前者运行的作用域。传入的函数接收三个参数,数组元素的值、位置和数组本身。迭代方法会遍历数组,并对其中的每个元素执行指定的函数。这些迭代方法的返回值可能会受到传入的函数的影响,返回值的主要区别是:

        以 $filter(\ )$ 为例,我们可以这样使用迭代方法:

console.log([1, 2, 3, 4].filter(function(value, index, array) {
    return value > 2;
})); // "3,4"

3.9 归并方法

        归并方法用于归并数组,接收两个参数,第一个为对每个元素执行的函数,第二个参数(可选)为归并初始值。指定的函数接收四个参数——前一个元素的值,当前元素的值、位置和数组本身,返回值作为第一个参数传入下次调用。如果没有提供第二个参数,归并方法的第一次迭代将发生在数组第二项元素,第一项元素为初始值。EMCAScript提供了两个归并方法—— $reduce(\ )$ 和 $reduceRight(\ )$ ,前者正序遍历,后者逆序遍历。使用归并方法求和的程序为:

console.log([1, 2, 3].reduce(function(pre, cur, index, array) {
    return pre + cur;
})); // 6

JavaScript中的数组