javaScript特殊对象-数组及数组方法(一)

114 阅读6分钟

「这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战」。

highlight: a11y-dark

数组

数组声明

  • 数组是一种特殊的对象,适用于存储和管理有序的数据项
  • 访问数组属性使用方括号,实际上是来自于对象的语法,与obj[key]相同,只是对象是使用数字作为键(key)。
  • 创建一个空数组有以下两种语法(一般情况下,使用第二种方式的时候多一点):
    let arrOne = new Array();
    let arrTwo = []; 
    let arrThree = [1,2,3]
    使用下标获取数组元素,下标从0开始
    console.log(arrThree[0]); // 1
    替换元素
    arrThree[2] = 5;
    console.log(arrThree[2]); // 5
    向数组中添加新元素
    arrThree[3] = 3;
    console.log(arrThree); // [1,2,5,3]
  • 数组可以存储任何数据类型的元素
    let arrFour = ['Apple', { name: 'John' }, true, () => { console.log('hello world'); },4]
    arrFour[3](); //hello world

关于数组的length

  • 数组的长度属性length
  • 当我们在修改数组的时候,数组的length属性会自动更新;准确的来说,它实际上不是数组的元素个数,而是最后一个元素的索引值加一
    let arrFive = ['a','b','c','d'];
    console.log(arrFive.length); // 4
    let lengthArr = []; 
    lengthArr[123] = "Apple";
    console.log( lengthArr.length ); // 124
  • 清除数组最简单的方法就是
    let clearArr = [1,2,3];
    clearArr.length = 0; //该过程是不可逆的截断数组

多维数组

  • 数组里的元素也可以是数组,将其作为多维数组
let two = [
    ['a','b','c'],
    [1,2,3],
    [true,false,true],
]
console.log(two[1][2]); // 3

数组方法

数组的toString方法

  • 数组实现的有自己的toString方法,会返回以逗号间隔的元素列表
    let toStringArr = ['a','b','v','c']
    console.log(toStringArr.toString()) // a,b,v,c
    let toStringArrTwo = [['a','b'],['v','c']]
    console.log(toStringArrTwo.toString()) // a,b,v,c
    let toStringArrThree = [{name:'zs',age: 26},['v','c']]
    console.log(toStringArrThree.toString()); //[object Object],v,c

添加/移除、插入数组元素

数组的pop/push、shift/unshift方法

pop

  • 取出并返回数组的最后一个元素
let popArr = ['pop1','pop2','pop3']
console.log(popArr.pop()); // pop3
console.log(popArr); // [ 'pop1', 'pop2' ]

push

  • 在数组末端添加元素
let pushArr = ['push1','push2'];
pushArr.push('push3');
console.log(pushArr); // [ 'push1', 'push2', 'push3' ]
// push多个元素进去
pushArr.push('push4','push5');
console.log(pushArr); // [ 'push1', 'push2', 'push3', 'push4', 'push5' ]

shift

  • 取出数组的第一个元素并返回
let shiftArr = ["shift1", "shift2", "shift3"];
console( fruits.shift() ); // shift1 
console( fruits ); // [shift2, shift3]

unshift

  • 在数组的首端
let unshiftArr = ['unshift1','unshift2'];
unshiftArr.unshift('unshift3');
console.log(unshiftArr); // [ 'unshift3', 'unshift1', 'unshift2' ]
// unshift多个元素进去
unshiftArr.unshift('unshift4','unshift5');
console.log(unshiftArr); // [ 'unshift4', 'unshift5', 'unshift3', 'unshift1', 'unshift2' ]

性能

  • push/pop方法运行比较快而unshift/shift运行比较慢(作用于数组的末端比首端的操作快)
  • 原因:
  • 以shift来说,从首端取出一个元素时,只获取并移除下标0对应的元素是不够的,还需要修改其它元素,对剩下的元素进行重新编号,对数组进行shift操作时必须要做三件事情:
  1. 移除索引为0的元素
  2. 把剩下所有元素向左移动,把索引1改成0,2改成1 ... length-1改成length-2
  3. 更新 length 属性
  • 因此数组内的元素越多,移动时需要的时间就越长,也就需要越多的内存操作。
  • unshift 也是一样的,只是移动方向向右,增加索引值
  • push/pop 它们不需要移动任何元素,如果从末端移除一个元素,pop方法只需要清理索引值并更新length属性即可。由于pop方法不需要移动任何元素,因此数组中的其它元素都保留了各自的索引值,所以比shift性能好一点,同样的,push也一样,只需在数组末端添加一个元素,更新length属性即可,无需任何元素修改索引值。

splice方法

  • 在数组中,删除数组元素是非常常见的操作,由于数组是一个对象,我们可以尝试使用delete来进行删除操作
    delete 删除操作
    let deleteArr = ['zs','ls','ww','zl'];
    delete deleteArr[1];
    console.log(deleteArr); // [ 'zs', <1 empty item>, 'ww', 'zl' ]
    console.log(deleteArr.length); // 4
  • 通过上面的实例可以看出来,虽然元素被删除了,但是数组仍然有四个元素,数组长度length=4.
  • 由于delete object.key是通过key(键值)来移除对应的值,这种方式对应对于对象来讲是完全可以的,
  • 对于数组来讲,我们是更希望移除相应的元素之后剩下的元素能够移动并占据被释放的位置,得到一个更短的数组。
  • 为了实现这种功能可以使用splice方法,splice方法很强大,它不单单能删除指定的元素,还能够在指定的位置插入和添加元素。

语法及实例

  • 语法: arr.splice(start[,deleteNumber, el1, el2, ..., eln])
  • start:开始索引
  • deleteNumber: 删除元素个数[可以省略不写]
  • el1 ... eln:添加的新元素[可以省略不写]
  • 数组arr从索引start开始进行修改,首先删除deleteNumber个元素(如果不写删除个数的话,将会删除start索引之后的所有元素)然后再插入el1 ... eln的所有新元素
  • 实例代码块 移除从指定索引开始的元素
    let spliceArr = [1,2,3,4,5,6];
    spliceArr.splice(3);
    console.log(spliceArr); // [1,2,3]
  • 移除从指定索引开始的一定数量的元素
let spliceArr = [1,2,3,4,5,6];
spliceArr.splice(3,2);
console.log(spliceArr); // [1, 2, 3, 6]
spliceArr.splice(3,4);
console.log(spliceArr); // [1, 2, 3]
  • 移除指定长度元素后并插入新的元素
let spliceArr = [1,2,3,4,5,6];
spliceArr.splice(3,2,'a','b');
console.log(spliceArr); //[ 1, 2, 3, 'a', 'b', 6 ]
  • 当只是在指定索引位置开始插入新的元素时,而不删除,需要给第二个删除个数的参数传入0或者空值之类的参数
let spliceArr = [1,2,3,4,5,6];
spliceArr.splice(3,0,'a','b');
console.log(spliceArr); //[ 1, 2, 3, 'a', 'b',4, 5, 6 ]
  • 支持负向索引
let arr = [1, 2, 5]; 
//从索引 -1(尾端前一位) 删除 0 个元素,然后插入 3 和 4 
arr.splice(-1, 0, 3, 4);
console.log( arr ); // [1, 2, 3, 4, 5]

slice方法

  • 该方法会返回一个新的数组,将所有从索引start到end(不包含end)的数组项复制到一个新的数组,start和end都可以为负数,在负数的情况下(最后一位是-1...-length),从末尾开始计算索引
  • 语法 arr.slice([start],[end])
let sliceArr = ['s','l','i','c','e']
console.log(arr.slice(1,3)); // [ 'l', 'i' ]
console.log(arr.slice(-2)); // [ 'i', 'c', 'e' ]

concat方法

  • arr.concat 创建一个新数组,其中包含来自于其他数组和其他项的值
  • 语法 arr.concat(arg1, arg2...)
  • 可以接收任意数量的参数,这个参数可以是一个数组,也可以是一个数值;如果参数是一个数组,其中的元素会被全部复制,否则值只制参数本身
  • 返回的结果包含原数组arr以及添加的参数arg1, arg2 ...
let concatArr1 = [1,2];
console.log(concatArr1.concat([3,4])); //[ 1, 2, 3, 4 ]
console.log(concatArr1.concat([3,4],5,6)); //[ 1, 2, 3, 4, 5, 6 ]
console.log(concatArr1.concat([{name:'zs',age: 24},{name:'mlxg',age: 25}])); //[ 1, 2, { name: 'zs', age: 24 }, { name: 'mlxg', age: 25 } ]
console.log(concatArr1.concat([[1,2],[3,4]]));//[ 1, 2, [ 1, 2 ], [ 3, 4 ] ]
  • concat只复制数组元素,就算是那些类数组对象也会被作为一个整体进行添加进去;当类数组元素具有Symbol.isConcatSpreadable属性时,且该属性为true,会被当做数组来处理,将此对象中的元素一一添加进去:
let arr = [1, 2];
let arrayLike = {
  0: "something",
  length: 1
};
console.log(arr.concat(arrayLike)); //[ 1, 2, { '0': 'something', length: 1 } ]
arrayLike[Symbol.isConcatSpreadable] = true;
console.log(arr.concat(arrayLike)); // [ 1, 2, 'something' ]