阅读 192

(JS基础)Array

JavaScript 的Array对象是用于构造数组的全局对象,数组是类似于列表的高阶对象。

基本操作

创建

数组内存放的可以是任意类型的数据。

let arr1 = [1, { a: 1 }, 'b', [22, 11], true];
let arr2 = new Array(1, { a: 1 }, 'b', [22, 11], true);
let arr3 = Array(1, { a: 1 }, 'b', [22, 11], true);

// 创建指定长度的空数组
let arr4 = new Array(3);    // 长度为3的空数组  [ <3 empty slots> ]
let arr4 = Array(3);    // 效果同上
复制代码

获取和修改成员

获取数组成员的方式:[]运算。

let arr = [1, { a: 1 }, 'b', [22, 11], true];
console.log(arr[1]);    // { a: 1 }
arr[0] = 100;
console.log(arr);       // [100, { a: 1 }, 'b', [22, 11], true]
复制代码

引用类型

ObjectArray的基类,和Object一样,数组也是引用类型的数据。所以简单的赋值并不能复制数组,只是单纯的把"指针"复制给新的变量。看如下例子:

let arr = [1, 2, 3];
let arr2 = arr;
arr2[1] = 200;
console.log(arr);    // [ 1, 200, 3 ]复制代码

可以看出,arr2的修改也会对arr造成影响,其原因是两者指向是同一个对象。要想两者互不影响,必须使用"深拷贝"。(看另一篇文章讲述深拷贝)

成员的增减

添加/删除数组成员的方法有几个,可以从任意位置操作任意多个的成员,且都会改变数组的长度。下面介绍最简单的从数组尾部添加/删除。

let arr = [1, 2, 3];
arr.pop();
console.log(arr);    // [ 1, 2 ]
arr.push(100);
console.log(arr);    // [ 1, 2, 100 ]复制代码

还有一种"特别的"删除成员方法,就是使用delete运算符,但不会改变数组长度,只会把成员变为"空":

let arr = [1, 2, 3];
delete arr[0];
console.log(arr);    // [ <1 empty slot>, 2, 3 ]复制代码


实例属性

目前常用的属性就一个:length。用于获取数组的长度


实例方法

这些方法都是对数组的增删改查。其中"增"、"删"、"改"都会改变原数组。

  • push(el1[, el2[, ...[, elN]]]):将一个或多个元素添加到数组的末尾,并返回该数组的新长度。
  • unshift(el1[, el2[, ...[, elN]]]):将一个或多个元素添加到数组的开头,并返回该数组的新长度。
  • fill(value[, start[, end]]):用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。不包括终止索引。
// 【fill】
let arr2 = Array(3).fill('a');
console.log(arr2);  // [ 'a', 'a', 'a' ]
复制代码

  • pop():从数组中删除最后一个元素,并返回该元素的值。
  • shift():从数组中删除第一个元素,并返回该元素的值。

  • copyWithin(target[, start[, end]]):参数都是索引值。浅复制数组的一部分到同一数组中的另一个位置,并返回它,原数组长度不变。
  • splice(start[, deleteCount[, item1[, item2[, ...]]]])删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容start​表示修改开始的索引值,负数表示末尾开始;deleteCount表示移除的个数,可选,非负整数,超出边界取边界值;item1, item2, ...表示要添加的元素,省略则只删除。
  • reverse():把数组顺序颠倒,并返回该数组。
  • sort([compareFunction]):以指定的算法对数组排序compareFunction表示规定排序规则的函数,接收两个参数:currentEl当前元素,nextEl下一个元素。compareFunction返回 -1 表示currentEl < nextEl;返回 0 表示currentEl = nextEl;返回 1 表示currentEl < nextEl
// 【sort】
let arr = [ 'b', 'a', 4, 3, 2, 1 ]
arr.sort((a, b) => {
  return a - b
})
console.log(arr);   // [ 'b', 'a', 1, 2, 3, 4 ]
复制代码

  • indexOf(searchElement[, fromIndex])返回在数组中可以找到一个给定元素第一个索引值,如果不存在,则返回 -1 。searchElement表示要查找的元素;fromIndex表示开始查找的索引值,可以为负数,表示从末尾开始。
  • lastIndexOf(searchElement[, fromIndex]):和indexOf()类似,只是从末尾开始,不多介绍。

遍历

正常情况下,遍历都不会修改原数组,除非你利用索引值对原数组进行修改。方法内传入的callback表示回调函数,该回调函数可传入三个参数,分别是:当前值value,当前索引值index,调用该方法的整个数组arraythisArg则表示执行callback时作为this对象的值。

  • filter(callback[, thisArg]):以callback为条件过滤数组。即对数组每个元素执行一次callback返回callback返回值为true的元素组成的新数组,所有元素的callback都是false则返回[]
  • forEach(callback[, thisArg]):对数组的每个元素执行一次callback函数,无返回值
  • map(callback[, thisArg]):对每个元素执行callback函数,返回以callback的返回值所组成的新数组
  • reduce(callback[, initialValue]):以callback函数每次返回的值进行特定的运算,直到把数组所有元素"累积"成一个值。和上面的方法不一样,callback接收的参数有四个:accumulator表示上一次调用回调时返回的累积值,初始值等于initialValuecurrentValue表示正在处理的元素;currentIndex表示正在处理的元素的索引值,可选;array表示调用该方法的数组。initialValue表示计算的初始值,可选。
  • reduceRight(callback[, initialValue]):与reduce()类似,只是从右边开始,不多介绍。
let arr = [1, 2, 3, 4, 5];
// 【filter】
let result1 = arr.filter(value => {
  return value > 2
});
console.log(result1);    // [ 3, 4, 5 ]
// 【reduce】
let result2 = arr.reduce((sum, current) => {
  return sum += current
}, 15);
console.log(result2);    // 30
复制代码

测试

返回的结果都是布尔值,表示是否含有特定值或满足特定的条件。callback函数接受的参数参照上面的"遍历"。

  • every(callback[, thisArg]):测试一个数组内的所有元素是否都能通过callback函数的测试
  • some(callback[, thisArg]):测试一个数组内的所有元素是否有其中一个通过callback函数的测试
  • includes(valueToFind[, fromIndex]):查找数组是否包含指定元素valueToFind表示要查找的元素,fromIndex表示开始查找的索引值,默认为 0 ,可以为负数,表示从末尾开始。
// 【every】
let arr = [1, 2, 3, 4];
let result = arr.every((value) => {
  return value > 1
});
console.log(result);    // false
复制代码

迭代器

  • entries():返回一个新的Array Iterator对象,该对象包含数组中每个索引的键/值对。
  • keys():返回一个新的Array Iterator对象,该对象包含数组中每个索引值。(对于数组,该方法实用性不大)
  • value():返回一个新的Array Iterator对象,该对象包含数组中每个值。
// 【entries】
let arr = ['a', 'b', 'c'];
let iterator1 = array1.entries();
console.log(iterator1.next().value);    // [0, "a"]
console.log(iterator1.next().value);    // [1, "b"]
复制代码

浅拷贝

以下方法都是返回新数组,不会改变原数组。

  • slice(begin, end)提取数组,从索引beginend(不包括end)的浅拷贝到一个新数组,返回新数组beginend都是索引值,都可以是负数,表示从末尾开始,若值超过数组边界,取边界值。
  • flat(depth)depth指定要提取嵌套数组的结构深度,默认值为 1。按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。简单说就是把多维数组平铺,返回新数组,原数组不变
// 【concat】
let arr = [1, 2, 3, 4];
let newArr = arr.concat([11, 22], 33);
console.log(newArr);    // [ 1, 2, 3, 4, 11, 22, 33 ]
// 【flat】
let arr = [1, [2, 3], [4, [5, 6], 7], 8]
let result4 = arr.flat(1);
let result5 = arr.flat(2);
console.log(result4);    // [ 1, 2, 3, 4, [5, 6], 7, 8 ]
console.log(result5);    // [ 1, 2, 3, 4, 5, 6, 7, 8 ]复制代码

其他

  • join([separator])用指定的分隔符把数组所有元素拼接成字符串(即除了最后一个,每个元素转化成字符串并加上分隔符,最后把所有字符串按顺序连接),返回该字符串。separator表示分隔符,默认为","。
  • toLocaleString():返回一个字符串表示数组中的元素。数组中的元素将使用各自的 toLocaleString 方法转成字符串,这些字符串将使用一个特定语言环境的字符串(例如一个逗号 ",")隔开。
  • toString():返回一个字符串,表示指定的数组及其元素。
  • [Symbol.iterator]:通过这个方式可以改写数组对象默认的迭代器方法,当然了,一般情况不建议改写。


静态方法

目前静态方法有三个:

  • from(arrayLike[, mapFn[, thisArg]]):从一个类似数组或可迭代对象中创建一个新数组实例,返回新数组。例如,函数内部的arguments对象就是一个类数组,Array.from(arguments)可以得到一个数组对象。arrayLike表示要转换成数组的伪数组对象或可迭代对象;mapFn表示新数组中的每个元素会执行该回调函数,可选;thisArg表示执行回调函数mapFnthis对象,可选。
  • of(element0[, element1[, ...[, elementN]]])创建一个包含指定元素的新数组。与Array构造函数类似,两者唯一差别在于参数为单个整数,Array构造函数得到的是指定长度的空数组,而Array.of()得到的是包含该数字的一个数组。
  • isArray(target):用于确定target的值是否是一个Array。返回布尔值


展开运算符(...)

这部分内容在另一篇文章有介绍。


其他

reduce() 方法的妙用

前面介绍到reduce()可以将数组的成员以特定的方法"累积"成特定的值。

加入数组存放的不是"值",而是"方法",数组就可以作为一个"方法栈",把某个值经过"方法栈"后得到计算结果。例子如下:

let funcStack = [
  n => n + 2,
  n => n ** 3,
  n => n * 8
]
let input = 0,
  result = funcStack.reduce((computed, fn) => {
    return fn(computed);
  }, input);
// ((0 + 2) ^ 3) * 8 = 64
console.log(result);  // 64复制代码

输入值input依次经历了三个数学运算,得到最终的结果。









文章分类
前端
文章标签