前情提要

重学 Array 之一中,我们讲到了数组的基本概念,还有定义数组的两种方式。通过对一维数组的介绍,我们引出了对二维数组相关的知识的讲解,最后说到了数组中两个关键的属性 length 和下标,这两个属性在我们平时对数组的操作中起着关键的作用,当然他们的特性也是非常有意思的。关于具体的内容,大家可以回过头去看看重学 Array 之一的内容。

今天我们就来说说数组原型上对元素增删操作的相关方法吧!

元素增删

下面方法的介绍将按照字母顺序进行!

concat()

concat() 方法用于合并两个或多个数组。

⚠️注意:此方法不会更改现有数组,而是返回一个新数组

语法

  1. const new_array = old_array.concat(value1[, value2[, ...[, valueN]]])

concat() 方法会创建一个新的数组,它由被调用的对象中的元素组成,每个参数的顺序依次是该参数的元素(如果参数是数组)或参数本身(如果参数不是数组)。它不会递归到嵌套数组参数中。

concat() 方法不会改变 this 或任何作为参数提供的数组,而是返回一个浅拷贝,它包含与原始数组相结合的相同元素的副本。 原始数组的元素将复制到新数组中,如下所示:

  • 对象引用(而不是实际对象):concat() 将对象引用复制到新数组中。 原始数组和新数组都引用相同的对象。 也就是说,如果引用的对象被修改,则更改对于新数组和原始数组都是可见的。 这包括也是数组的数组参数的元素。

  • 数据类型如字符串,数字和布尔(不是StringNumberBoolean 对象):concat将字符串和数字的值复制到新数组中。

⚠️注意:数组/值在连接时保持不变。此外,对于新数组的任何操作(仅当元素不是对象引用时)都不会对原始数组产生影响,反之亦然。

示例

  1. // 将两个数组合并成一个数组
  2. [1, 2, 3].concat(['a', 'b']) // [1, 2, 3, "a", "b"]
  3. // 将三个数组合并成一个数组
  4. const arr1 = [1, 2, 3]
  5. const arr2 = ['a', 'b', 'c']
  6. const arr3 = ['!', '@']
  7. arr1.concat(arr2, arr3)
  8. // [1, 2, 3, "a", "b", "c", "!", "@"]
  9. // 将三个值连接到数组
  10. var alpha = ['a', 'b', 'c'];
  11. var alphaNumeric = alpha.concat(1, [2, 3]);
  12. console.log(alphaNumeric);
  13. // results in ['a', 'b', 'c', 1, 2, 3]
  14. // 合并数组并保留引用
  15. var num1 = [[1]];
  16. var num2 = [2, [3]];
  17. var nums = num1.concat(num2);
  18. console.log(nums);
  19. // results in [[1], 2, [3]]
  20. // 向 num1 数组的第一个元素 push 一个值
  21. num1[0].push(4);
  22. console.log(nums);
  23. // [[1, 4], 2, [3]] 数组内引用的值改变了

pop()

pop() 方法从数组中删除最后一个元素,并返回该元素的值。

⚠️注意:此方法更改数组的长度

语法

  1. arr.pop()

pop 方法有意具有通用性。该方法和 call()apply() 一起使用时,可应用在类似数组的对象上。pop方法根据 length 属性来确定最后一个元素的位置。如果不包含 length 属性或 length 属性不能被转成一个数值,会将length 置为0,并返回 undefined。如果调用 pop() 方法的数组为空,它也返回 undefined。

示例

  1. let myFish = ["angel", "clown", "mandarin", "surgeon"];
  2. let popped = myFish.pop();
  3. console.log(myFish);
  4. // ["angel", "clown", "mandarin"]
  5. console.log(popped);
  6. // surgeon

push()

push() 方法将一个或多个元素添加到数组的末尾,并返回该数组的新长度。

语法

  1. arr.push(element1, ..., elementN)

push() 方法有意具有通用性。该方法和 call()apply() 一起使用时,可应用在类似数组的对象上。push() 方法根据 length 属性来决定从哪里开始插入给定的值。如果 length 不能被转成一个数值,则插入的元素索引为 0,包括 length 不存在时。当 length 不存在时,将会创建它。

⚠️注意:唯一的原生类数组(array-like)对象是 Strings,尽管如此,它们并不适用该方法,因为字符串是不可改变的。

示例

  1. // 😁例子1:添加元素到数组
  2. var sports = ["soccer", "baseball"];
  3. var total = sports.push("football", "swimming");
  4. console.log(sports);
  5. // ["soccer", "baseball", "football", "swimming"]
  6. console.log(total);
  7. // 4
  8. // 😁例子2:合并两个数组
  9. var vegetables = ['parsnip', 'potato'];
  10. var moreVegs = ['celery', 'beetroot'];
  11. // 相当于 vegetables.push('celery', 'beetroot')
  12. // 或者 vegetables.concat(moreVegs)
  13. Array.prototype.push.apply(vegetables, moreVegs);
  14. console.log(vegetables);
  15. // ['parsnip', 'potato', 'celery', 'beetroot']
  16. // 😁例子3:像数组一样操作对象
  17. var obj = {
  18. length: 0,
  19. addElem: function addElem (elem) {
  20. [].push.call(this, elem);
  21. }
  22. };
  23. obj.addElem({});
  24. obj.addElem({});
  25. console.log(obj.length);
  26. // 2

shift()

shift() 方法从数组中删除第一个元素,并返回该元素的值。

⚠️注意:此方法更改数组的长度

语法

  1. arr.shift()

shift() 方法移除索引为 0 的元素(即第一个元素),并返回被移除的元素,其他元素的索引值随之减 1。如果 length 属性的值为 0 (长度为 0),则返回 undefined。

shift() 方法并不局限于数组,这个方法能够通过 callapply 方法作用于类似数组的对象上。但是对于没有 length 属性(从0开始的一系列连续的数字属性的最后一个)的对象,调用该方法可能没有任何意义。

示例

  1. let myFish = ['angel', 'clown', 'mandarin', 'surgeon'];
  2. console.log('调用 shift 之前: ' + myFish);
  3. // "调用 shift 之前: angel,clown,mandarin,surgeon"
  4. var shifted = myFish.shift();
  5. console.log('调用 shift 之后: ' + myFish);
  6. // "调用 shift 之后: clown,mandarin,surgeon"
  7. console.log('被删除的元素: ' + shifted);
  8. // "被删除的元素: angel"

slice()

slice() 方法返回一个新的数组对象,这个对象是一个由 begin 和 end(不包括end)决定的原数组的浅拷贝。

⚠️注意:原始数组不会被改变

语法

  1. arr.slice();
  2. // [0, end]
  3. arr.slice(begin);
  4. // [begin, end]
  5. arr.slice(begin, end);
  6. // [begin, end)
  • begin:可选参数,从该索引处开始提取原数组中的元素(从0开始)。如果该参数为负数,则表示从原数组中的倒数第几个元素开始提取,slice(-2) 表示提取原数组中的倒数第二个元素到最后一个元素(包含最后一个元素)。如果省略 begin,则 slice 从索引 0 开始。

  • end:可选参数,在该索引处结束提取原数组元素(从0开始)。slice 会提取原数组中索引从 begin 到 end 的所有元素(包含begin,但不包含end)。slice(1, 4) 提取原数组中的第二个元素开始直到第四个元素的所有元素 (索引为 1, 2, 3的元素)。如果该参数为负数, 则它表示在原数组中的倒数第几个元素结束抽取。 slice(-2,-1) 表示抽取了原数组中的倒数第二个元素到最后一个元素(不包含最后一个元素,也就是只有倒数第二个元素)。如果 end 被省略,则slice 会一直提取到原数组末尾。如果 end 大于数组长度,slice 也会一直提取到原数组末尾。

slice 不修改原数组,只会返回一个浅复制了原数组中的元素的一个新数组。原数组的元素会按照下述规则拷贝:

  • 如果该元素是个对象引用 (不是实际的对象),slice 会拷贝这个对象引用到新的数组里。两个对象引用都引用了同一个对象。如果被引用的对象发生改变,则新的和原来的数组中的这个元素也会发生改变。

  • 对于字符串、数字及布尔值来说(不是 StringNumber 或者 Boolean 对象),slice 会拷贝这些值到新的数组里。在别的数组里修改这些字符串或数字或是布尔值,将不会影响另一个数组。

如果向两个数组任一中添加了新元素,则另一个不会受到影响。

示例

  1. // 😁例子1:返回数组的一部分
  2. var fruits = ['Banana', 'Orange', 'Lemon', 'Apple', 'Mango'];
  3. var citrus = fruits.slice(1, 3);
  4. // fruits ['Banana', 'Orange', 'Lemon', 'Apple', 'Mango']
  5. // citrus ['Orange','Lemon']
  6. // 😁例子2:使用 slice 方法从 myCar 中创建一个 newCar.
  7. var myHonda = { color: 'red', wheels: 4, engine: { cylinders: 4, size: 2.2 } };
  8. var myCar = [myHonda, 2, "cherry condition", "purchased 1997"];
  9. var newCar = myCar.slice(0, 2);
  10. // 输出myCar, newCar,以及各自的myHonda对象引用的color属性.
  11. console.log('myCar = ' + JSON.stringify(myCar));
  12. console.log('newCar = ' + JSON.stringify(newCar));
  13. console.log('myCar[0].color = ' + JSON.stringify(myCar[0].color));
  14. console.log('newCar[0].color = ' + JSON.stringify(newCar[0].color));
  15. // 改变myHonda对象的color属性.
  16. myHonda.color = 'purple';
  17. console.log('The new color of my Honda is ' + myHonda.color);
  18. //输出myCar, newCar中各自的myHonda对象引用的color属性.
  19. console.log('myCar[0].color = ' + myCar[0].color);
  20. console.log('newCar[0].color = ' + newCar[0].color);

splice()

splice() 方法通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。

⚠️注意:此方法会改变原数组

语法

  1. array.splice(start[, deleteCount[, item1[, item2[, ...]]]])
  • start:指定修改的开始位置(从 0 计数)。如果超出了数组的长度,则从数组末尾开始添加内容;如果是负值,则表示从数组末位开始的第几位(从 -1 计数,这意味着 -n 是倒数第 n 个元素并且等价于 array.length-n);如果负数的绝对值大于数组的长度,则表示开始位置为第 0 位。

  • deleteCount:可选参数,整数值,表示要移除的数组元素的个数。如果 deleteCount 大于 start 之后的元素的总数,则从 start 后面的元素都将被删除(含第 start 位)。如果 deleteCount 被省略了,或者它的值大于等于array.length - start(也就是说,如果它大于或者等于start之后的所有元素的数量),那么start之后数组的所有元素都会被删除。如果 deleteCount 是 0 或者负数,则不移除元素。这种情况下,至少应添加一个新元素。

  • item1, item2, …:可选要添加进数组的元素,从 start 位置开始。如果不指定,则 splice() 将只删除数组元素。

⚠️注意:如果添加进数组的元素个数不等于被删除的元素个数,数组的长度会发生相应的改变。

示例

  1. // 😁例子1:从第 2 位开始删除 0 个元素,插入“drum”
  2. var myFish = ["angel", "clown", "mandarin", "sturgeon"];
  3. var removed = myFish.splice(2, 0, "drum");
  4. // 运算后的 myFish: ["angel", "clown", "drum", "mandarin", "sturgeon"]
  5. // 被删除的元素: [], 没有元素被删除
  6. // 😁例子2:从第 2 位开始删除 0 个元素,插入“drum” 和 "guitar"
  7. var myFish = ['angel', 'clown', 'mandarin', 'sturgeon'];
  8. var removed = myFish.splice(2, 0, 'drum', 'guitar');
  9. // 运算后的 myFish: ["angel", "clown", "drum", "guitar", "mandarin", "sturgeon"]
  10. // 被删除的元素: [], 没有元素被删除
  11. // 😁例子3:从第 3 位开始删除 1 个元素
  12. var myFish = ['angel', 'clown', 'drum', 'mandarin', 'sturgeon'];
  13. var removed = myFish.splice(3, 1);
  14. // 运算后的 myFish: ["angel", "clown", "drum", "sturgeon"]
  15. // 被删除的元素: ["mandarin"]
  16. // 😁例子4:从第 2 位开始删除 1 个元素,插入“trumpet”节
  17. var myFish = ['angel', 'clown', 'drum', 'sturgeon'];
  18. var removed = myFish.splice(2, 1, "trumpet");
  19. // 运算后的 myFish: ["angel", "clown", "trumpet", "sturgeon"]
  20. // 被删除的元素: ["drum"]
  21. // 😁例子5:从第 0 位开始删除 2 个元素,插入"parrot"、"anemone"和"blue"节
  22. var myFish = ['angel', 'clown', 'trumpet', 'sturgeon'];
  23. var removed = myFish.splice(0, 2, 'parrot', 'anemone', 'blue');
  24. // 运算后的 myFish: ["parrot", "anemone", "blue", "trumpet", "sturgeon"]
  25. // 被删除的元素: ["angel", "clown"]
  26. // 😁例子6:从第 2 位开始删除 2 个元素节
  27. var myFish = ['parrot', 'anemone', 'blue', 'trumpet', 'sturgeon'];
  28. var removed = myFish.splice(myFish.length - 3, 2);
  29. // 运算后的 myFish: ["parrot", "anemone", "sturgeon"]
  30. // 被删除的元素: ["blue", "trumpet"]
  31. // 😁例子7:从倒数第 2 位开始删除 1 个元素节
  32. var myFish = ['angel', 'clown', 'mandarin', 'sturgeon'];
  33. var removed = myFish.splice(-2, 1);
  34. // 运算后的 myFish: ["angel", "clown", "sturgeon"]
  35. // 被删除的元素: ["mandarin"]
  36. // 😁例子8:从第 2 位开始删除所有元素节
  37. var myFish = ['angel', 'clown', 'mandarin', 'sturgeon'];
  38. var removed = myFish.splice(2);
  39. // 运算后的 myFish: ["angel", "clown"]
  40. // 被删除的元素: ["mandarin", "sturgeon"]

unshift()

unshift() 方法将一个或多个元素添加到数组的开头,并返回该数组的新长度。

语法

  1. arr.unshift(element1, ..., elementN)

unshift() 方法会在调用它的类数组对象的开始位置插入给定的参数。unshift() 特意被设计成具有通用性,这个方法能够通过 callapply 方法作用于类数组对象上。不过对于没有 length 属性(代表从0开始的一系列连续的数字属性的最后一个)的对象,调用该方法可能没有任何意义。

⚠️注意:如果传入多个参数,它们会被以块的形式插入到对象的开始位置,它们的顺序和被作为参数传入时的顺序一致。 于是,传入多个参数调用一次 unshift ,和传入一个参数调用多次 unshift (例如,循环调用),它们将得到不同的结果。

示例

  1. // 😁例子1:传入多个参数调用一次 unshift
  2. let arr = [4,5,6];
  3. arr.unshift(1,2,3); // 6
  4. console.log(arr); // [1, 2, 3, 4, 5, 6]
  5. // 传入一个参数调用多次 unshift
  6. arr = [4,5,6]; // 重置数组
  7. arr.unshift(1); // 4
  8. arr.unshift(2); // 5
  9. arr.unshift(3); // 6
  10. console.log(arr); // [3, 2, 1, 4, 5, 6]
  11. // 😁例子2:
  12. let arr = [1, 2];
  13. arr.unshift(0); // 3
  14. // arr is [0, 1, 2]
  15. arr.unshift(-2, -1); // 5
  16. // arr is [-2, -1, 0, 1, 2]
  17. arr.unshift([-4, -3]); // 6
  18. // arr is [[-4, -3], -2, -1, 0, 1, 2]
  19. arr.unshift([-7, -6], [-5]); // 8
  20. // arr is [ [-7, -6], [-5], [-4, -3], -2, -1, 0, 1, 2 ]

总结

到这里,关于数组原型上七个关于元素增删操作的方法就说完了,都是一些比较简单的方法,其中 slice 和 splice 可能比较复杂一些,不错多跑点测试代码就好了。下一篇我们会说一些关于数组循环遍历的方法。