Array

ECMAScript的数组每个槽位可以存储任意类型,同时也是动态大小,自动增长的。

1.创建数组

let colors = new Array();
let colors2 = []; 			//字面量

let colors3 = new Array(3);  //初始化长度
let names = new Array("Greg");  //包含一个元素

let values1 = new Array("red", "blue", "green");
let values2 = [1,2,3,];  //包含1,2,3三个元素


2.Array.from()与Array.of()

from()用于将类数组结构转换为数组实例,而of()用于将一组参数转换为数组实例。

  • Array.from()的第一个参数是一个类数组对象,即任何可迭代的结构,或者有一个length属性和可索引元素的结构。

    例如:字符串、Map、Set、数组(执行浅复制)、实现 Symbol.iterator 的对象、arguments对象、迭代器对象

    console.log(Array.from("Matt")); // ["M", "a", "t", "t"]
    
    const m = new Map().set(1, 2).set(3, 4);
    console.log(Array.from(m)); // [[1, 2], [3, 4]]
    
    // arguments对象可以被轻松地转换为数组
    function getArgsArray() {
    	return Array.from(arguments);
    }
    console.log(getArgsArray(1, 2, 3, 4)); // [1, 2, 3, 4]

    Array.from()还接收第二个可选的映射函数参数,这个函数可以直接增强新数组的值。还可以接收第三个可选参数,用于指定映射函数中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()可以把一组参数转换为数组。用来代替下面写法

    function getArgsArray() {
    	return Array.prototype.slice.call(arguments);
        //return Array.from(arguments);
    }
    console.log(Array.of(1, 2, 3, 4)); // [1, 2, 3, 4]
    console.log(Array.of(undefined)); // [undefined]

3.数组空位

const options = [,,,,,]; // 创建包含5个元素的数组
console.log(options.length); // 5
console.log(options); // [,,,,,]

ES6新增方法会将空位当作 undefined 包括:for-of、Array.from()、Array.of()

ES6之前的方法有其他行为

const options = [1,,,,5];
// map()会跳过空位置
console.log(options.map(() => 6)); // [6, undefined, undefined, undefined, 6]
// join()视空位置为空字符串
console.log(options.join('-')); // "1----5"

为了避免行为差异,可使用显式undefined代替空位


4.索引

如果使用了超过最大索引的索引,数组长度会自动拓展到输入索引。

length属性也不是只读的,可以通过修改length属性删除或增加元素,如添加会用undefined填充。


5.检测数组

//1.通常情况有效
if (value instanceof Array){
// 操作数组
}

//2.推荐使用
if (Array.isArray(value)){
// 操作数组
}


6.迭代器方法

Array的原型上有3个用于检索数组内容的方法:
keys()、values()和entries()。keys()返回数组索引的迭代器,values()返回数组元素的迭代器,而entries()返回索引/ 值对的迭代器

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"]]

解构可以在循环中拆分entries()迭代器产生的键/值对

const a = ["foo", "bar", "baz", "qux"];
for (const [idx, element] of a.entries()) {
	console.log(idx);
	console.log(element);
}
// 0
// foo
//...


7.复制和填充

  • fill() 填充函数,接收三个参数分别为:填充内容、开始索引(可选默认0)、结束索引(可选默认到尾部)

    const zeroes = [0, 0, 0, 0, 0];
    zeroes.fill(6, 3);
    console.log(zeroes); // [0, 0, 0, 6, 6]
    zeroes.fill(0); // 重置

  • copyWithin() 执行数组内部的浅复制,接收三个参数分别为:粘贴的位置、开始复制的位置(可选默认0)、结束复制的位置(可选默认到尾部)

    ints = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
    
    ints.copyWithin(2, 0, 6); // 复制0-5之间的元素,粘贴到索引2开始的空间
    console.log(ints); // [0, 1, 0, 1, 2, 3, 4, 5, 8, 9]

8.转换为字符串

toString()、toLocaleString() 返回由对应方法将每个元素转换字符串拼接而成的逗号分隔的字符串。

join() 方法接收一个参数作为分隔符(可选默认为逗号)

let colors = ["red", "green", "blue"];
console.log(colors.join(",")); // red,green,blue
console.log(colors.join("||")); // red||green||blue

注:如果数组中某一项是null或undefined,转换时会特殊对待以空字符串("")表示


9.栈与队列方法

  • push() 方法接收任意数量的参数,并将它们添加到数组尾部,返回数组长度
  • pop() 方法则用于删除数组的最后一项,同时减少数组的length值,返回被删除的项
  • shift() 方法它会删除数组的第一项并返回它,然后数组长度减1。
  • unshift() 方法在数组开头添加任 意多个值,然后返回新的数组长度。


10.排序

  • reverse() 方法使原数组元素反向排列

  • sort() 方法 默认升序排列元素,先对每一项调用String() ,再按字典序,多数情况下这得不到想要的结果,
    为此sort() 可以接收一个比较函数。比较函数接收两个参数,如果第一个参数应该排在第二个参数前面,就返回负值,以此类推。

    let values = [0, 1, 5, 10, 15];
    // 传一个降序函数
    values.sort((a, b) => a < b ? 1 : a > b ? -1 : 0); 
    console.log(values); // 15,10,5,1,0

    如果元素只是数组升序函数也可以这么写

    function compare(value1, value2){
    	return value2 - value1;
    }


11.操作方法

  • concat() 方法返回连接所有参数数组的副本(打平),如果参数不是数组则直接添加到数组中。

  • slice() 截取函数返回副本 方法接收两个参数:开始索引(可选默认0)、结束索引(不包含、可选默认到尾部)

  • splice() 方法修改原数组 接收三个参数:插入或删除位置、删除数量、要添加的元素(可选) 返回被删除的元素组成的数组

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


12.搜索方法

  • indexOf()、lastIndexOf()和includes() 都执行严格相等( === ),都支持设置起始搜索位置,前两个返回索引,includes返回布尔值

  • find()和findIndex() 接收一个断言函数,断言函数接收3个参数:元素、索引和数组本身,断言函数返回真值,表示匹配同时搜索停
    止,也可以接收第二个参数指定断言函数内部this。  这两个方法分别返回第一个匹配元素和索引。

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


13.迭代方法

ECMAScript为数组定义了5个迭代方法。每个方法接收两个参数: 以每一项为参数运行的函数,以及可选的作为函数运行上下文的作用域对象(影响函数中this的值)。传给每个方法的函数接收3个参数:数组元素、元素索引和数组本身。

  • every():如果对每一项函数都返回true,则返回true。
  • filter() :  返回函数返回true的元素组成的数组。
  • forEach():只对每一项都调用函数,无返回值。
  • map():对每一项都调用函数,返回由调用结果构成的数组。
  • some():如果有一个元素调用函数后返回true,则返回true。


14.归并方法

reduce()和 reduceRight() 两个方法归并的方向不同。这两个方法都会迭代数组的所有项,并构建一个最终返回值。
这两个方法都接收两个参数:归并函数,可选的作为归并起点的初始值。归并接收4个参数:上一个归并值、当前项、当前项的索引和数组本身。函数返回值都会作为下一次调用的第一个参数。如果没有给这两个方法传入第二个参数(作为归并起点值),则第一次迭代将从数组的第二项开始,因此传给归并函数的第一个参数是数组的第一项,第二个参数是数组的第二项。

//利用归并累加数组
let values = [1, 2, 3, 4, 5];
let sum = values.reduce((prev, cur, index, array) => prev + cur);
console.log(sum); // 15