JavaScript 数组对象 Array

前言

在 JavaScript 中引用类型除了 Object 外,最常用的恐怕就是 数组 Array 了。 都说 JavaScript 中万物基于对象(但我觉得这句话有些时候也是有些坑的), 所以 Array 对象也有很多它内置的方法。
JavaScript 是弱类型语言, 所以我们不用声明就可以直接使用了, 但这样是比较不推荐的。 JavaScript 中的数组也是个有序列表, 但和其他语言有所不同的是, JavaScript 数组中的每一项都可以保存任何类型的数据。 有点像 Python 中的列表, 我们可以用数组中的第一项保存一个数字, 第二项保存一个字符串, 而第三项可以保存一个 Object, 没有任何限制。 并且其数组大小是动态调整的, 可以随数据增长而自动增大数组大小。


创建数组的方法

在 JavaScript 中创建数组有两种方法:

  • 第一种是使用 Array 的构造函数

    1
    2
    3
    4
    var 数组名 = new Array();
    var 数组名2 = new Array(20); //向Array对象构造函数传递参数指定数组大小
    var 数组名3 = new Array("Tflin", "Lyfei", "Zshan"); //创建具体项的数组
    var 数组名4 = Array(); //也可以省略new操作符
  • 第二种是使用是使用数组字面量表示法

    1
    2
    3
    var 数组名 = []; //创建一个空数组
    var 数组名2 = ["Tflin", "Lyfei", "Zshan"]; //创建具体项的数组
    var 数组名3 = [,,,,]; //虽然这样也行,但这是有歧义的,不建议!会创建一个人包含5或6项的数组

数组在使用字面量表示法时, 和对象一样, 是不会调用Array构造函数的(Firefox 3 及更早版本除外)。


访问数组

和其他语言的数组并无多大区别, 使用数组的下标来访问数组

1
2
3
4
5
var name = ["Tflins",  "Lyfei", "Zshan"];
console.log(name[0]); //显示第一项
name[1] = "Lxyu"; //修改第二项
name[3] = "Whzhen" //新增第四项, 数组大小是动态调整的
consloe.log(name[4]) //undefined

在方括号中的索引表示要访问数组的值,如果索引小于数组中的项数 (arrName.length), 则返回数组中对应的值, 如果大于数组中的项数, 则返回 undefined 未定义。
数组的项数保存在 length 属性中。如

1
2
var name = ["Tflins",  "Lyfei", "Zshan"]; //创建一个包含3个字符串的数组
console.log(name.length); //3

但 javascript 中 length 属性并不是只读的, 因此可以调整 length 的值, 来移除数组中的项或者添加新项。

1
2
3
var name = ["Tflins",  "Lyfei", "Zshan"]; //创建一个包含3个字符串的数组
name.length = 2;
console.log(name[2]); //undefined

我们已经把 length 的值改为 2, 所以访问下标为 2(第三项) 的值时, 得到一个特殊的值 undefined。
当然利用 length 我们也可以很方便的在数组添加新的一项, 因为数组中最后一项的索引始终是 (length - 1) 。 如

1
2
3
var name = ["Tflins",  "Lyfei", "Zshan"]; //创建一个包含3个字符串的数组
name[name.length] = "Whzhen"; //在位置 3 添加一项
name[name.length] = "Lxyu"; //在位置 4 添加一项


检测数组

在 javascript 中, 我们可以用 type of() 方法来检测其数据类型, 但是有个奇怪的事情, 就是我们使用 type of 检测数组时, 它会返回一个 Object, 而不是 Array, 这是有歧义的事情。
当然我们也可以使用 instanceof 来进行检测, 就可以得到满意的答案, 如

1
2
var name = ["Tflins",  "Lyfei", "Zshan"]; 
consloe.log(name instanceof Array); //true

不过在使用 instanceof 时, 它的问题在于, 如果网页中含有多个框架, 则便存在连个以上不同的全局执行环境, 从而可能存在两个以上不同版本的 Array 构造函数, 如果从一个框架向另一个框架传递数组, 那么传入的数组将与另一个框架中的数组具有不同的构造函数。
所以在 ECMAScript 5 中新增了 Array.isArray() 方法, 这个方法就是用来检测一个值是不是一个数组的, 也不管其是在哪个全局执行环境创建的。 用法如下

1
2
var name = ["Tflins",  "Lyfei", "Zshan"]; 
consloe.log(Array.isArray(name)); //true


转换方法

javascript 中所有对象都具有 toLocaleString()、toString()、valueOf()方法。

  • valueOf()
    调用这个方法返回的是数组本身

    1
    2
    var name = ["Tflins",  "Lyfei", "Zshan"]; 
    consloe.log(name.valueOf()); //Tflins, Lyfei, Zshan
  • toString()
    这个方法会返回一个由数组中每个值得字符串形式拼接而成的字符串, 并由逗号隔开

    1
    2
    var name = ["Tflins",  "Lyfei", "Zshan"]; 
    consloe.log(name.valueOf()); //Tflins, Lyfei, Zshan
  • toLocaleString()
    toLocaleString() 是把数组转换为本地数组,并返回结果。
    LocaleString() 会根据你机器的本地环境来返回字符串, 它和 toString() 返回的值在不同的本地环境下使用的符号会有微妙的变化。
    因此使用toString()是保险的, 返回唯一值的方法,它不会因为本地环境的改变而发生变化。 如果是为了返回时间类型的数据, 推荐使用LocaleString()。 若是在后台处理字符串,必使用toString()。


数组 栈方法

在 JavaScript 中, 数组也提供了类似数据结构中的一些方法。 可以让数组像栈一样, 具有后进先出的特点。

  • push() 推入方法
    push() 可以接受任意数量但值, 并把它们逐个添加到数组末尾, 修改并返回 length 属性。

    1
    2
    3
    4
    var name = ["Tflins",  "Lyfei", "Zshan"]; 
    var count = name.push("Lxyu", "Cbyi"); //推入两项
    console.log(count); //5
    consloe.log(name.valueOf()); //Tflins, Lyfei, Zshan, Lxyu, Cbyi
  • pop() 弹出方法
    pop() 则是从数组末尾移除最后一项, 减少 length 的值, 然后返回被移除(弹出)的一项

    1
    2
    3
    4
    var name = ["Tflins",  "Lyfei", "Zshan"]; 
    var item = name.pop(); //弹出一项
    console.log(item); //Zshan
    consloe.log(name.valueOf()); //Tflins, Lyfei

数组 队列方法

队列是一种 FIFO 新进新出的数据结构, 从列表末端添加新项, 从前端移除数据项, 因此可以使用 push() 和 shift() 方法来模拟这一结构。

  • shift()
    这个方法能够移除数组中的第一项, 并返回该项, 同时减少 length 的长度 1 。
    1
    2
    3
    4
    5
    var name = ["Tflins",  "Lyfei", "Zshan"]; 
    var count = name.push("Lxyu"); //推入一项
    console.log(count); //4
    var item = name.shift(); //取得移除的第一项
    consloe.log(name。valueOf()); //Lyfei, Lxyu

在 JavaScript 中,还位数组提供了一个 unshift() 方法, 顾名思义就是 shift() 的用途反过来。

  • unshift()
    该方法能在数组前端添加任意个项的值, 并返回新数组的长度 , 所以可以配合 pop() 方法来反向模拟队列。 即在数组前端添加新项, 末端移除项。 如
    1
    2
    3
    4
    5
    var name = ["Tflins",  "Lyfei", "Zshan"]; 
    var count = name.unshift("Lxyu"); //在数组前端添加一项
    console.log(count); //4
    var item = name.pop(); //取得移除的第最后一项
    consloe.log(name.valueOf()); //Lxyu, Tflins, Lyfei

重排序方法

在数组中, 有两个可以直接用来重排序的方法: reverse() 与 sort(),+++++++++++++++++++++++++ 这两个方法返回的都是重排序后的数组。

  • reverse()
    这个方法可以反转数组的顺序, 如

    1
    2
    3
    var arr = [1, 2, 3, 4];
    arr.reverse();
    alert(arr); //4, 3, 2, 1
  • sort()
    这个方法在默认的情况下按升序排序数组, 为了实现排序 sort() 会调用每个数组项的 toString() 方法, 将其转换成字符串, 因此 sort() 方法比较的是字符串, 如

    1
    2
    3
    var arr = [4, 3, 2, 1, 44, 5, 55];
    arr.sort();
    alert(arr); //1, 2, 3, 4, 44, 5, 55

    在上述例子中数值 5 虽然小于 44, 但 sort() 比较的是字符串, “44” 在 “5” 的前面, 所以便产生了这样的结果。 所以 sort() 在多种情况下并不是最佳方案。 为了解决这一问题, 可以使用 sort() 方法来接受一个比较函数, 这个比较函数用于决定哪个值位于哪个值的前面, 如

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    //比较函数
    function compare(value1, value2) {
    if(value1 < value2) {
    return -1;
    } else if(value1 > value2) {
    return 1;
    } elae {
    return 0;
    }
    }

    var arr = [4, 3, 2, 1, 44, 5, 55];
    arr.sort(compare);
    alert(arr); //1, 2, 3, 4, 5, 44, 55

    上述例子中, 使用 sort() 接受了一个比较函数, 所以在排序数值时仍然保持了正确的升序。


数组操作方法

JavaScript 为操作数组提供了很多的方法,

  • concat()
    concat() 方法会创建一个副本数组, 然后将接收到的参数添加到这个副本的末尾, 最后返回新构建的整个数组,简单的说就是合并。 如

    1
    2
    3
    4
    var arr1 = [1, 2, 3];
    var arr2 = arr1.concat("Tflin", [4, 5]);
    alert(arr1); //1, 2, 3
    alert(arr2); //1, 2, 3, Tflin, 4, 5
  • slice()
    这个函数有点类似 Python 中的切片, 它能够基于当前数组中的一个或多个项创建一个新数组。 slice() 方法接收一或两个参数。 如果有一个参数, 则返回该项到数组末尾的所有项。 如果有两个参数, 第一个参数为起始项, 第二个参数为末尾项, 返回起始项到末尾项之间所有的项, 但不包括末尾项。 如

    1
    2
    3
    4
    5
    var arr1 = [1, 2, 345, 6];
    var arr2 = arr1.slice(1) //一个参数,返回该项到数组末尾的所有项
    var arr3 = arr1.slice(2, 4) //两个参数, 回起始项到末尾项之间所有的项, 但不包括末尾项。
    alert(arr2); //2
    alert(arr3); //3, 4

    slice() 方法接收的参数, 如果是负数的话, 则使用参数与数组的 length 相加得到相应位置, 如在 length 为 5 的数组中 slice(-2, -1) 与 slice(3, 4) 得到的结果是一样的。 结束位置小于起始位置则返回空数组。

  • splice()
    这个方法恐怕是数组中最强大的方法了, 它有很多种用法, 主要功能是向数组中部插入项。 如
    • 删除
      splice(0, 2) 第一个参数是要删除的第一项的位置, 第二个参数则是要删除的项数。 splice(0, 2) 便是删除数组中的前两项。
    • 插入
      splice() 可以向指定的位置插入项, 需要接受三个参数,
------ 本文结束 ------

版权声明

Tflin's Blog by Tan Feng Lin is licensed under a Creative Commons BY-NC-ND 4.0 International License.
谭丰林创作并维护的Tflin's Blog博客采用创作共用保留署名-非商业-禁止演绎4.0国际许可证
本文首发于Tflin's Blog 博客( http://tflin.com ),版权所有,侵权必究。