和其他语言里的数组一样,ECMAScript里的数组也是一组有序数据,但不同的是ECMAScript里数组可以存储不同的值,这意味着可以创建一个数组,它的第一个元素是字符串。第二个元素是数值,第三个是对象。ECMAScript 数组也是动态大小的,会随着数据添加而自动增长。

4.1 创建数组

JavaScript里有两种方式来创建数组

4.1.1 使用 Array 构造函数来创建数组

  1. var 数组名 = new Array();
  2. var arr = Array(8); //创建一个数组长度为8的数组
  3. var arr = Array(); //创建一个空数组
  4. let colors = new Array(3); //创建一个包含 3 个元素的数组
  5. let names = new Array('Greg'); //创建一个只包含一个元素,即字符串'Grag'的数组
  • Array函数的首字母要大写
  • 创建时可以省略new操作符
  • 创建数组时可以给构造函数传一个值。这个时候就有点问题了,因为如果这个值时数值,则会创建一个长度为指定数值的数组;而如果这个值时其他类型的,则会创建一个值包含该特定值的数组

    4.1.2 数组字面量表示法创建数组

    1. var 数组名 = []; //创建一个空数组
    2. var color = ['red','green','blue'];
    3. var num = [1,2,3]
  • 并未使用Array构造数组函数

  • 声明时赋值给数组,为空时创建空数组

    4.2 获取数组元素

    通过数组的索引来只想数组中确定的元素,数组的索引从0开始,所以最大索引永远比长度(length)少1

    1. var num = [1,2,3,4,5,6];
    2. console.log(num[2]) // 3

    4.3 数组长度(length)

    数组中元素的数量保存在 length 属性中,这个属性始终返回 0 或大于 0 的值

    1. let color = ['red','blue','green']; //创建一个包含 3 个字符串的数组
    2. let names = []; // 创建一个空数组
    3. alert(colors.length); // 3
    4. alert(names.length); // 0

    4.3.1 通过length来缩短数组

    1. let colors = ['red','blue','green'];
    2. color.length = 2;
    3. alert(colors[2]); // undefined
  • 数组 colors 一开始有 3 个值。将 length 设置为 2,就删除了最后一个(位置 2 的)值,因此 colors[2]就没有值了。

    4.3.2 通过length来加长数组

    1. color.length = 5;
    2. console.log(color); // 'red','blue','green' undefined undefined
  • 如果将length设置为大于数组元素的值,则新添加的元素都将以 undefined 填充

    数组的检测

    判断变量是否为数组时,

    • instanceof操作符在只有一个网页(因而只有一个全局作用域)的情况下,使用 instanceof 操作符就足矣
      1. let arr = [1,2,3],
      2. obj = {};
      3. console.log(arr instanceof Array); //true
      4. console.log(obj instanceof Array); //false
  • 使用 instanceof 的问题是假定只有一个全局执行上下文。如果网页里有多个框架,则可能涉及两个不同的全局执行上下文,因此就会有两个不同版本的 Array 构造函数

  • 如果要把数组从一个框架传给另一个框架,则这个数组的构造函数将有别于在第二个框架内本地创建的数组

    • Array.isArray()这个方法的目的就是确定一个值是否为数组,而不用管它是在哪个全局执行上下文中创建的。
      1. let arr = [5,4,3,2,1];
      2. obj = {};
      3. console.log(Array.isArray(arr)); // true
      4. console.log(Array.isArray(obj)); // false

      4.4 栈方法(push 和 pop)

      数组对象可以向栈一样,也就是最近添加的项先被删除。数据项的插入(称为推入,push)和删除(称为弹出,pop)只在栈的一个地方发生,即栈顶。ECMAScript 数组提供了 push() 和 pop() 方法,以实现类似栈的行为。
  • push()方法接受任意数量的参数,并将它们添加到数组末尾,返回数组的最新长度。

  • pop()方法则用于删除数组的最后一项,同时减少数组的length值,返回被删除的项。

    1. let colors = new Array(); //创建一个数组
    2. let count = colors.push('red','green'); //推入两项
    3. alert(count); // 2
    4. count = colors.push('blak'); //再推入一项
    5. alert(count); // 3
    6. let item = colors.pop(); //取得最后一项
    7. alert(item); // black
    8. alert(colors.length); // 2
  • 这里创建了一个当作栈来使用的数组(注意不需要任何额外的代码,push() 和 pop() 都是数组的默认方法)。

  • 首先,使用 push()方法把两个字符串推入数组末尾,将结果保存在变量 count 中(结果为 2)。
  • 然后,再推入另一个值,再把结果保存在 count 中。因为现在数组中有 3 个元素,所以 push()返回3.
  • 在调用 pop()时,会返回数组的最后一项,即字符串’black’。此时数组还有两个元素。

push()、pop()方法可以和数组的其他方法一起使用:

  1. let colors = ['red','blue'];
  2. colors.push('brown'); //再添一项
  3. colors[3] = 'block'; //再添一项
  4. let item = colors.pop(); //取得最后一项
  5. alert(item); //black

4.5 队列方法(unshift 和 shift)

队列以先进先出(FIFO, First-In-First-Out)形式限制访问。队列在列表末尾添加数据,但从列表开头获取数据。因为有了在数据末尾添加数据的push()方法,所以要模拟队列就差一个从数组开头取得数据的方法了。

  • 这个数组方法叫 shift(),他会删除数组的第一项并返回它,然后数组长度减 1.
  • 使用 shift()和push(),可以把数组当成队列来使用:

    1. let colors = new Array(); // 创建一个数组
    2. let count = colors.push('red','green'); // 推入两项
    3. alert(count); // 2
    4. count = colors.push('black'); // 再推入一项
    5. alert(count); // 3
    6. let item = colors.shift(); // 取得第一项
    7. alert(item); // red
    8. alert(colors.length); // 2

    shift()方法也为数组提供了unshift()方法。unshift执行跟 shift() 相反的操作:

  • 在数组开头添加任意多个值,然后返回新的数组长度。

  • 通过使用 unshift() 和 pop(),可以在相反方向上模拟队列,即在数组开头添加新数据,在数组末尾取得数据
  • 如下例所示:

    1. let colors = new Array(); // 创建一个数组
    2. let count = colors.unshift('red','greed'); // 从数组开头推入
    3. alert(count); // 2
    4. count = colors.unshift('black'); // 再推入一项
    5. alert(count); // 3
    6. let item = colors.pop(); // 取得最后一项
    7. alert(item); // greed
    8. alert(colors.length); // 2

    4.6 排序方法

    数组有两个方法可以用来对元素重新排序:reverse()sort()

  • reverse()方法将数组反向排序

  • sort()会按照升序重新排列数组元素,即最小的值在前面,最大的值在后面。为此,sort()会在每一项上调用 String() 转型函数,然后比较字符串来决定顺序。即使数组的元素都是数值,也会先把数组转换为字符串再比较、排序。
    1. let values = [0,1,5,10,15];
    2. values.reverse();
    3. alert(values); // 15,10,5,1,0
    reverse()方法来反向排列数组

  1. let values = [0,1,5,10,15];
  2. values.sort();
  3. alert(values);// 0,1,10,15,5

sort()方法如果不加比较函数的话,默认为字典排序,即为按照首字母大小以及首位数字大小排序


比较方法:比较函数接受两个参数,如果第一个参数应该排在第二个参数前面,就返回负值;如果两个参数相等,就返回 0;如果第一个参数应该排在第二个参数后面,就返回正值。

  1. function compare(a,b) {
  2. return a - b; //如果a>b,a排在b后面,为从小到大排
  3. }
  • 当 a - b > 0 时,调换a、b位置,使之从小往大排序

    1. function compare(a,b) {
    2. return b - a; //如果a<b,a排在b后面,为从大到小排
    3. }
    4. let a = [5,3,2,1,6,4]
    5. console.log(a.sort(compare)) //[6,5,4,3,2,1]
  • 如果传入“function(a,b){ return a-b;}”,则为升序

  • 如果传入“function(a,b){ return b-a;}”,则为降序

    4.7 操作方法

    4.7.1 concat()方法

    concat()方法可以在现有数组全部元素基础上创建一个新数组。他首先会创建一个当前数组的副本,然后再把它的参数添加到副本末尾,最后返回这个新构建的数组。如果传入一个或多个数组,则concat()会把这些数组的每一项都添加到结果数组。如果参数不是数组,则直接把它们添加到结果数组末尾。

    1. let colors = ['red','greed','blue'];
    2. let colors2 = colors.concat('yellow',['black','brown']);
    3. console.log(colors); // ['red','greed','blue']
    4. console.log(colors2); // ['red',greed','blue','yellow','black','brown']

    4.7.2 slice()

    方法 slice() 用于创建一个包含原有数组中一个或多个元素的新数组。slice()方法可以接收一个或两个参数:

  • 返回元素的开始索引和结束索引

  • 如果只有一个参数,则 slice() 会返回该索引到数组末尾的所有元素
  • 如果有两个参数,则 slice() 返回从开始索引到结束索引对应的所有元素,其中不包含结束索引对应的元素。记住,这个操作不影响原始数组

    1. let colors = ['red','green','blue','yellow','purple'];
    2. let colors2 = colors.slice(1);
    3. let colors3 = colors.slice(1,4);
    4. alert(colors2); // green,blue,yellow,purple
    5. alert(colors3); // green,blue,yellow

    返回时不反回第二个参数代表的位置的元素,此时从 1 开始到位置 4 结束,仅仅返回1、2、3这三个位置的元素。
    注意:如果 slice()的参数有负值,那么就以数值长度加上这个负值的结果确定位置。比如,在包含 5 个元素的数组上调用 slice(-2,-1),就相当于调用 slice(3,4)。如果结束位置小于开始位置,则返回空数组。

    4.7.3 splice()方法

    或许最强的数组方法就属 splice()了,使用它的方式可以有很多种。splice()的主要目的是在数组中间插入元素,担忧 3 种不同的方式使用这个方法。

  • 删除。需要给 splice()传 2 个参数:要删除的第一个元素的位置和要删除的元素数量。可以从数组中删除任意多个元素,比如 splice(0,2)会删除前面两个元素。

  • 插入。需要给 splice()传 3 个参数:开始位置、0(要删除的元素数量)和要插入的元素,可以在数组中指定的位置插入元素。第三个参数之后还可以传第四个、第五个参数,乃至任意多个要插入的元素。比如,splice(2,0,’red’,’green’)会从数组位置 2 开始插入字符串 ‘red’和 ‘green’。
  • 替换。splice()在删除元素的同时可以在指定位置插入新元素,同意要传入 3 个参数:开始位置、要删除元素的数量和要插入的任意多个元素。要插入的元素数量不一定跟删除的元素数量一致。比如,splice(2,1,’red’,’green’)会在位置 2 删除一个元素,然后从该位置开始向数组中插入’red’ 和 ‘green’.

splice()方法始终返回这样一个数组,它包含从数组中被删除的元素(如果没有删除元素,则返回空数组)。

  1. let colors = ['red','green','blue'];
  2. let removed = colors.splice(0,1); // 删除第一项
  3. alert(colors); // green,blue
  4. alert(removed); // red,只有一个元素的数组
  5. removed = colors.splice(1,0,'yellow','orange'); // 在位置 1 插入两个元素
  6. alert(colors); // green,yellow,orange,blue
  7. alert(removed); //空数组
  8. removed = colors.splice(1,1,'red','purple'); // 插入两个值,删除一个元素
  9. alert(colors); // green,red,purple,orange,blue
  10. alert(removed); // yellow,只有一个元素的数组

4.8 转换方法

前面提到过,所有对象都有 toLocaleString()、toString()和 valueOf()方法。其中,valueOf()返回的还是数组本身。而 toString()返回由数组中每个值的等效字符串拼接而成的一个逗号分隔的字符串。也就是说,对数组的每个值都会调用其 toString()方法,以得到最终的字符串。

  1. let colors = ["red", "blue", "green"]; // 创建一个包含 3 个字符串的数组
  2. alert(colors.toString()); // red,blue,green
  3. alert(colors.valueOf()); // red,blue,green
  4. alert(colors); // red,blue,green

4.8.1 join()方法

join()方法接收一个参数,即字符串分隔符,返回包含所有项的字符串。

  1. let colors = ["red", "green", "blue"];
  2. alert(colors.join(",")); // red,green,blue
  3. alert(colors.join("||")); // red||green||blue
  • 这里在 colors 数组上调用了 join()方法,得到了与调用 toString()方法相同的结果。
  • 传入逗号,结果就是逗号分隔的字符串。最后一行给 join() 传入了双竖线,得到了字串”red||green||blue”。
  • 如果不给 join()传入任何参数,或者传入 undefined,则仍然使用逗号作为分隔符。