创建数组
Array构造函数
不要求必须带 new 关键字,不带时会自动补上
var arr1 = new Array(); //创建一个空数组
var arr2 = new Array(20); // 创建一个包含20项的数组
var arr3 = new Array("lily","lucy","Tom"); // 创建一个包含3个字符串的数组
var arr4 = Array(1000).fill(0) // 创一个1000个0的数组
字面量
var arr4 = []; //创建一个空数组
var arr5 = [20]; // 创建一个包含1项数据为20的数组
var arr6 = ["lily","lucy","Tom"]; // 创建一个包含3个字符串的数组
Array 构造函数还有两个ES6新增的用于创建数组的静态方法:from() 和 of() 。
from() 用于将类数组结构转换为数组实例,而of() 用于将一组参数转换为数组实例。
- 创建二维数组 ```javascript const arrayNumbers = Array.from(Array(2), () => new Array(4));
const arrayNumbers = Array(2) .fill() .map(() => Array(4));
<a name="yS3am"></a>
### Array.from()
Array.from() 的第一个参数是一个类数组对象,即任何可迭代的结构,或者有一个length 属性和可索引元素的结构.。这个方法用于替代在ES6之前常用的`Array.prototype.slice.call(arguments) `
> 典型的“类似数组的对象”是**函数的arguments对象,以及大多数 DOM 元素集,还有字符串。只要是部署了iterator接口的数据结构,Array.from都能将其转为数组**
```javascript
// 所谓类似数组的对象,本质特征只有一点,即必须有length属性。
// 因此,任何有length属性的>对象,都可以通过Array.from方法转为数组
Array.from({length: 5}) // [undefined, undefined, undefined, undefined, undefined]
// 字符串会被拆分为单字符数组
console.log(Array.from("Matt")); // ["M", "a", "t","t"]
// arguments对象可以被轻松地转换为数组
function getArgsArray() {
return Array.from(arguments);
}
console.log(getArgsArray(1, 2, 3, 4)); // [1, 2, 3,4]
Array.from() 还接收第二个可选的映射函数参数。这个函数可以直接增强新数组的值,而无须像调用Array.from().map() 那样先创建一个中间数组。还可以接收第三个可选参数,用于指定映射函数中this 的值。但这个重写的this 值在箭头函数中不适用。
const a1 = [1, 2, 3, 4];
const a2 = Array.from(a1, x => x**2);
console.log(a2); // [1, 4, 9, 16]
Array.of()
Array.of() 可以把一组参数转换为数组。
Array.of() 和 Array 构造函数之间的区别在于处理整数参数:Array.of(2) 创建一个具有单个元素 2 的数组,而 Array(2) 创建一个长度为2的空数组
let items = new Array(2) ;
console.log(items.length) ; // 2
items = Array.of(2);
console.log(items.length); // 1
Array.isArray()
使用instanceof
的问题是假定只有一个全局执行上下文。如果网页里有多个框架,则可能涉及两个不同的全局执行上下文,因此就会有两个不同版本的 Array 构造函数。如果要把数组从一个框架传给另一个框架,则这个数组的构造函数将有别于在第二个框架内本地创建的数组。
为解决这个问题,ECMAScript提供了 Array.isArray() 方法。这个方法的目的就是确定一个值是否为数组,而不用管它是在哪个全局执行上下文中创建的。
数组的空位
Array(3) // [, , ,] 注意,空位不是undefined
ES5 对空位的处理,已经很不一致了,大多数情况下会忽略空位。
- forEach(), filter(), reduce(), every() 和some()都会跳过空位。
- map()会跳过空位,但会保留这个值
- join()和toString()会将空位视为undefined,而undefined和null会被处理成空字符串。
- Array.from()方法会将数组的空位,转为undefined,也就是说,这个方法不会忽略空位。
- 扩展运算符(…)也会将空位转为undefined。
- copyWithin()会连空位一起拷贝。
- fill()会将空位视为正常的数组位置。for…of循环也会遍历空位。
- entries()、keys()、values()、find()和findIndex()会将空位处理成undefined ```javascript Array.apply(null, {length: 10}) Array.apply(null, Array(10)) Array.apply(null, new Array(10))
// 这三个方法相当于 Array(undefined, undefined, undefined, …)
// 其他写法 Array.from({length: 10}) Array(…Array(10))
<a name="b6FaX"></a>
## 常用方法
<a name="nD8DP"></a>
### 队列方法
- shift() :
- unshift():
<a name="bsJ2b"></a>
### 栈方法
- push() :
- pop():
```javascript
//删除数组最前面(头部)的元素
let first = fruits.shift();
//添加元素到数组的头部
let newLength = fruits.unshift('Strawberry')
//添加元素到数组的末尾
let newLength = fruits.push('Orange');
//删除数组末尾的元素
let last = fruits.pop();
搜索和位置方法
严格相等
indexOf() :从数组前头(第一项)开始向后搜索
lastIndexOf(): 从数组末尾(最后一项)开始向前搜索
- 都返回要查找的元素在数组中的位置,如果没找到则返回-1。
includes()
- 返回布尔值,表示是否至少找到一个与指定元素匹配的项。
let numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];
alert(numbers.indexOf(4)); // 3
alert(numbers.lastIndexOf(4)); // 5
alert(numbers.includes(4)); // true
断言函数
find() : 返回第一个匹配的元素
findIndex(): 返回第一个匹配元素的索引
find()与 findIndex()方法均接受两个参数:一个回调函数,一个可选值用于指定回调函数内部的 this。
该回调函数可接受三个参数:数组的某个元素,该元素对应的索引位置,以及该数组本身。
该回调函数应当在给定的元素满足你定义的条件时返回 true,而 find()和 findIndex()方法均会在回调函数第一次返回 true 时停止查找。
二者的区别是:find()方法返回匹配的值,而 findIndex()返回匹配位置的索引。
const array = [5, 12, 8, 130, 44];
const found = array.find(e => e > 10);
console.log(found);//12
排序算法
reverse() :
let values = [1, 2, 3, 4, 5];
values.reverse();
alert(values); // 5,4,3,2,1
sort() :
let values = [0, 1, 5, 10, 15];
function compare(a, b){
return a - b;
}
values.sort(compare);
alert(values); // 0,1,5,10,15
迭代器方法
- keys() 返回数组索引的迭代器
- values() 返回数组元素的迭代器
- entries() 返回索引/值对的迭代器
都返回一个新的Array Iterator对象
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"]]
// 使用ES6的解构可以非常容易地在循环中拆分键/值对:
for (const [idx, element] of a.entries()) {
alert(idx);
alert(element);
}
复制和填充方法
- fill(value,start,end)
- copyWithin(target.start,end) 浅复制数组的一部分到同一数组中的另一个位置,并返回它,不会改变原数组的长度 ```javascript const zeroes = [0, 0, 0, 0, 0]; // 用7填充索引大于等于1且小于3的元素 zeroes.fill(7, 1, 3); // 用6填充索引大于等于3的元素 zeroes.fill(6, 3); // 用5填充整个数组 zeroes.fill(5);
const ints = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] // 从ints中复制索引0开始的内容,插入到索引5开始的位置 // 在源索引或目标索引到达数组边界时停止 ints.copyWithin(5);
// 从ints中复制索引5开始的内容,插入到索引0开始的位置 ints.copyWithin(0, 5);
// 从ints中复制索引0开始到索引3结束的内容,插入到索引4开始的位置 ints.copyWithin(4, 0, 3);
<a name="ekI1R"></a>
### 转换方法
- valueOf()
- toString()
- toLocaleString()
valueOf() 返回的还是数组本身。而toString() 返回由数组中每个值的等效字符串拼接而成的一个逗号分<br />隔的字符串。也就是说,对数组的每个值都会调用其toString() 方法,以得到最终的字符串。
```javascript
let colors = ["red", "blue", "green"]; // 创建一个包含3个字符串的数组
alert(colors.toString()); // red,blue,green
alert(colors.valueOf()); // red,blue,green
alert(colors); // red,blue,green
首先是被显式调用的 toString() 和 valueOf() 方法,
它们分别返回了数组的字符串表示,即将所有字符串组合起来,以逗号分隔。
最后一行代码直接用 alert() 显示数组,因为 alert() 期待字符串,
所以会在后台调用数组的 toString() 方法,从而得到跟前面一样的结果。
toLocaleString() 方法也可能返回跟 toString() 和 valueOf() 相同的结果,但也不一定。它与另外两个方法唯一的区别是,为了得到最终的字符串,会调用数组每个值的 toLocaleString() 方法,而不是 toString() 方法。
继承的方法 toLocaleString() 以及 toString() 都返回数组值的逗号分隔的字符串。如果想使用不同的分隔符,则可以使用 join() 方法。 join() 方法接收一个参数,即字符串分隔符。
let colors = ["red", "green", "blue"];
alert(colors.join("||")); // red||green||blue
如果数组中某一项是 null 或 undefined ,则在 join() 、toLocaleString() 、toString() 和 valueOf() 返回的结果中会以空字符串表示。
操作方法
concat():
- 如果传入一个或多个数组,则 concat() 会把这些数组的每一项
- 都添加到结果数组。如果参数不是数组,则直接把它们添加到结果数组末尾。
let colors = ["red", "green", "blue"];
let colors2 = colors.concat("yellow", ["black","brown"]);
console.log(colors); // ["red", "green","blue"]
console.log(colors2); // ["red",
slice(begin,end) :
- 如果只有一个参数,则 slice() 会返回该索引到数组末尾的所有元素。
- 如果有两个参数,则 slice() 返回从开始索引到结束索引对应的所有元素,其中不包含结束索引对应的元素。
- 如果 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(start,delCount,item1,item2….) :开始位置、要删除的元素数量、要插入的元素
- 删除。需要给 splice() 传2个参数:要删除的第一个元素的位置和要删除的元素数量。可以从数组中删除任意多个元素,比如splice(0, 2) 会删除前两个元素。
- 插入。需要给 splice() 传3个参数:开始位置、0(要删除的元素数量)和要插入的元素,可以在数组中指定的位置插入元素。第三个参数之后还可以传第四个、第五个参数,乃至任意多个要插入的元素。比如, splice(2, 0, “red”, “green”) 会从数组位置2开始插入字符串 “red” 和 “green” 。
- 替换。 splice() 在删除元素的同时可以在指定位置插入新元素,同样要传入3个参数:开始位置、要删除元素的数量和要插入的任意多个元素。要插入的元素数量不一定跟删除的元素数量一致。比如,splice(2, 1, “red”, “green”) 会在位置2删除一个元素,然后从该位置开始向数组中插入 “red” 和 “green”
```javascript 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,只有一个元素的数组
<a name="4C8k9"></a>
####
<a name="p3YR6"></a>
#### 迭代方法
**这些方法都不改变调用它们的数组。**
```javascript
(function(currentValue,index,arr), thisArg)
-currentValue 必须。当前元素的值
-index 可选。当前元素的索引值
-arr 可选。当前元素属于的数组对象
-thisArg 可选。对象作为该执行回调时使用,传递给函数,用作 "this" 的值。
如果省略了 thisValue,或者传入 null、undefined,那么回调函数的 this 为全局对象。
注意:如果使用箭头函数表达式来传入函数参数, thisArg 参数会被忽略,因为箭头函数在词法上绑定了 this 值
- forEach() :对数组每一项都运行传入的函数,没有返回值。
- map() :对数组每一项都运行传入的函数,返回由每次函数调用的结果构成的数组。
- 只是遍历元素则可用forEach。
- 需要根据原数组得到新的数组使用map。
- filter() :对数组每一项都运行传入的函数,函数返回 true 的项会组成数组之后返回。
这个方法非常适合从数组中筛选满足给定条件的元素
const fruits = ['apple', 'banana', 'grapes', 'mango', 'orange'];
const filterItems = (query) =>
fruits.filter((el) =>
el.toLowerCase().indexOf(query.toLowerCase()) > -1
);
console.log(filterItems('ap')); // ['apple', 'grapes']
- every() :对数组每一项都运行传入的函数,如果对每一项函数都返回 true ,则这个方法返回 true 。
- some() :对数组每一项都运行传入的函数,如果有一项函数返回true ,则这个方法返回 true 。
归并方法
- reduce(callback(accumulator, currentValue, index, array), initialValue)
- reduceRight()
这两个方法都会迭代数组的所有项,并在此基础上构建一个最终返回值。 reduce() 方法从数组第一项开始遍历到最后一项。而 reduceRight() 从最后一项开始遍历至第一项。
函数接收4个参数:上一个归并值、当前项、当前项的索引和数组本身。
调函数第一次执行时,accumulator 和currentValue的取值有两种情况:如果调用reduce()时提供了initialValue,accumulator取值为initialValue,currentValue取数组中的第一个值;如果没有提供 initialValue,那么accumulator取数组中的第一个值,currentValue取数组中的第二个值。
注意:如果没有提供initialValue,reduce 会从索引1的地方开始执行 callback 方法,跳过第一个索引。如果提供initialValue,从索引0开始。
let values = [1, 2, 3, 4, 5];
let sum = values.reduce((prev, cur, index, array) => prev + cur);
alert(sum); // 15