Javascript——Array

92 阅读6分钟

在 js 中,除了 Object,Array 应该就是 ECMAScript 中最常用的类型了。

一、创建数组,共两种方法,加上一种转化方法。

a. 构建函数创建

let a1 = new Array(); // []

let a2 = new Array(20); // [empty × 20]

let colors = new Array("red", "blue", "green"); // ['red', 'blue', 'green']

let nums = new Array(1,3,5); // [1, 3, 5]


在使用 Array 构造函数时,也可以省略 new 操作符。结果是一样的,比如:

let colors = Array(3); // 创建一个包含 3 个元素的数组

let names = Array("Greg"); // 创建一个只包含一个元素,即字符串"Greg"的数组


new操作符的作用:
(1) 在内存中创建一个新对象。 
(2) 这个新对象内部的[[Prototype]]特性被赋值为构造函数的 prototype 属性。
(3) 构造函数内部的 this 被赋值为这个新对象(即 this 指向新对象)。
(4) 执行构造函数内部的代码(给新对象添加属性)。 
(5) 如果构造函数返回非空对象,则返回该对象;否则,返回刚创建的新对象。


JavaScript构造函数new与不new的区别
任何函数只要使用 new 操作符调用就是构造函数,而不使用 new 操作符调用的函数就是普通函数。
其次,对于js内置的一些构造函数,例如ArrayObject等,如果没有加new操作符,其内部会判断是否加上new关键字。
若是普通的构造函数,当我们不加new关键字的时候,此时this指向的是globalthis全局对象。

b. 数组字面量表示法

let colors = ["red", "blue", "green"]; // 创建一个包含 3 个元素的数组

let names = []; // 创建一个空数组

let values = [1,2,]; // 创建一个包含 2 个元素的数组

c. 静态方法创建数组

Array 构造函数还有两个 ES6 新增的用于创建数组的静态方法:from()和 of()。from()用于将类数组结构转换为数组实例,而 of()用于将一组参数转换为数组实例。

Array.from()

第一个参数是一个类数组对象,即任何可迭代的结构,或者有一个 length 属性和可索引元素的结构。
第二个可选的映射函数参数,这个函数可以直接增强新数组的值。<br/>
第三个可选参数,用于指定映射函数中 this 的值。但这个重写的 this 值在箭头函数中不适用。

const a1 = [1, 2, 3, 4];

const a2 = Array.from(a1, x => x**2);

const a3 = Array.from(a1, function(x) {return x**this.exponent}, {exponent: 2});

console.log(a2); // [1, 4, 9, 16]

console.log(a3); // [1, 4, 9, 16]



Array.of()

Array.of()可以把一组参数转换为数组。这个方法用于替代在 ES6之前常用的 Array.prototype.slice.call(arguments),
一种异常笨拙的将 arguments 对象转换为数组的写法:

console.log(Array.of(1, 2, 3, 4)); // [1, 2, 3, 4]

console.log(Array.of(undefined)); // [undefined]

二、数组空位

使用数组字面量初始化数组时,可以使用一串逗号来创建空位(hole)。

const options = [,,,,,]; // 创建包含 5 个元素的数组

console.log(options.length); // 5

console.log(options); // [,,,,,]



ES6 之前的方法则会忽略这个空位,但具体的行为也会因方法而异:

const options = [1,,,,5];

// map()会跳过空位置

console.log(options.map(() => 6)); // [6, undefined, undefined, undefined, 6]

// join()视空位置为空字符串

console.log(options.join('-')); // "1----5"


注意:
由于行为不一致和存在性能隐患,因此实践中要避免使用数组空位。如果确实需要空位,则可以显式地用 undefined 值代替。

三、 数组方法

1、检测数组方法:

if (value instanceof Array){

// 操作数组

}

if (Array.isArray(value)){

// 操作数组

}

2、迭代器方法:

const a = ["foo", "bar", "baz", "qux"];

// 因为这些方法都返回迭代器,所以可以将它们的内容

// 通过 Array.from()直接转换为数组实例

const aKeys = Array.from(a.keys());

const aValues = Array.from(a.values());

const aEntries = Array.from(a.entries());

console.log(aKeys); // [0, 1, 2, 3]

console.log(aValues); // ["foo", "bar", "baz", "qux"]

console.log(aEntries); // [[0, "foo"], [1, "bar"], [2, "baz"], [3, "qux"]]



3、填充方法:fill()
const zeroes = [0, 0, 0, 0, 0];

// 用 5 填充整个数组
zeroes.fill(5);
console.log(zeroes); // [5, 5, 5, 5, 5]
zeroes.fill(0);

// 用 7 填充索引大于等于 1 且小于 3 的元素
zeroes.fill(7, 1, 3);
console.log(zeroes); // [0, 7, 7, 0, 0];

4、复制方法:copyWithin()
let ints = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
ints.copyWithin(4, 0, 3);
alert(ints); // [0, 1, 2, 3, 0, 1, 2, 7, 8, 9]

5、转换方法
let colors = ["red", "blue", "green"]; // 创建一个包含 3 个字符串的数组
alert(colors.toString()); // red,blue,green
alert(colors.join()); // red,green,blue
alert(colors.join("||")); // red||green||blue

6、栈方法
ECMAScript 数组提供了 push()和 pop()方法,以实现类似栈的行为。

7、队列方法
使用 shift()和 push(),可以把数组当成队列来使用。
使用 unshift()和 pop(),可以在相反方向上模拟队列。

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

9、操作方法
concat()
可以在现有数组全部元素基础上创建一个新数组。它首先会创建一个当前数组的副本,然后再把它的参数添加到副本末尾,最后返回这个新构建的数组。
let colors = ["red", "green", "blue"];
let colors2 = colors.concat("yellow", ["black", "brown"]);
console.log(colors); // ["red", "green","blue"]
console.log(colors2); // ["red", "green", "blue", "yellow", "black", "brown"]

slice()
用于创建一个包含原有数组中一个或多个元素的新数组。
可以接收一个或两个参数:返回元素的开始索引和结束索引。
let colors = ["red", "green", "blue", "yellow", "purple"];
let colors2 = colors.slice(1);
let colors3 = colors.slice(1, 4);
alert(colors2); // green,blue,yellow,purple
alert(colors3); // green,blue,yellow

splice()
最强大的数组方法,主要目的是在数组中间插入元素,但有 3 种不同的方式(删除、插入、替换)使用这个方法。
删除:
let colors = ["red", "green", "blue"];
let removed = colors.splice(0,1); // 删除第一项
alert(colors); // green,blue
alert(removed); // red,只有一个元素的数组

插入:
removed = colors.splice(1, 0, "yellow", "orange"); // 在位置 1 插入两个元素
alert(colors); // green,yellow,orange,blue
alert(removed); // 空数组

替换:
removed = colors.splice(1, 1, "red", "purple"); // 插入两个值,删除一个元素
alert(colors); // green,red,purple,orange,blue
alert(removed); // yellow,只有一个元素的数组


10、搜索和位置方法
ECMAScript 提供了 3 个严格相等的搜索方法:indexOf()、lastIndexOf()和 includes()。

find()和 findIndex()方法使用了断言函数。这两个方法都从数组的最小索引开始。
find()返回第一个匹配的元素,findIndex()返回第一个匹配元素的索引。

const people = [{name: "Matt",age: 27},{name: "Nicholas",age: 29}];
alert(people.find((element, index, array) => element.age < 28));
// {name: "Matt", age: 27}
alert(people.findIndex((element, index, array) => element.age < 28));
// 0


11、迭代方法
every():对数组每一项都运行传入的函数,如果对每一项函数都返回 true,则这个方法返回 true。
filter():对数组每一项都运行传入的函数,函数返回 true 的项会组成数组之后返回。
forEach():对数组每一项都运行传入的函数,没有返回值。在forEach中并不能直接使用break、continue。
map():对数组每一项都运行传入的函数,返回由每次函数调用的结果构成的数组。
some():对数组每一项都运行传入的函数,如果有一项函数返回 true,则这个方法返回 true。
这些方法都不改变调用它们的数组。

12、归并方法
ECMAScript 为数组提供了两个归并方法:reduce()和 reduceRight()。
let values = [1, 2, 3, 4, 5];
let sum = values.reduce((prev, cur, index, array) => prev + cur);
alert(sum); // 15