10. Array API
- 类数组对象,可迭代对象,数组之间的区别?
- 类数组对象:
格式与数组结构类似,用于length,可以通过索引来访问或者修改里面的元素,但不能书用数组的方法
- 类数组对象:
类数组对可以通过Array.from()
来转换成数组,需要有length
属性来控制数组长度
注意:
1. 解析`length`时会使用`parseInt()`进行转换,默认为0
2. 如果`length`超过实际长度时,会用`undefined`填充,小于进行切片
const array = {0: 'apple', 1: 'orange', 2: 'strawberry', length: 'string'};
console.log(Array.from(array)); //[]
- 可迭代对象
Iterable
是实现了Symbol.iterator
方法的对象。
用for..of
循环认识它 :
为了让range
对象可迭代,我们需要为对象添加一个名为Symlbol.iterator
的方法
1. 当`for..of`循环启动时,它会调用这个方法(如果没有就会报错),这个方法必须返回一个**迭代器**<br />**(iterator)** ,这个迭代器拥有`next`方法
2. 当`for..of`循环希望取得下一个数值,它就调用这个对象的`next()`方法
3. `next()`方法必须返回格式为`{done:Boolean,value:any}`,当`done为true`时,表示循环结束,否则`value`是下一个值
let range = {
from: 1,
to: 5,
[Symbol.iterator]() {
// 1.它返回迭代器对象(iterator object):
// 2. 接下来,for..of 仅与下面的迭代器对象一起工作,要求它提供下一个值
return {
current: this.from,
last: this.to,
// 3. next() 在 for..of 的每一轮循环迭代中被调用
next() {
// 4. 它将会返回 {done:.., value :...} 格式的对象
if(this.current <= this.last) {
return {done: false,value:this.current++}
}else {
return {done:true};
}
}
}
}
};
for(let num of range) {
console.log(num);
}
- 罗列数组的常见方法
- 静态方法
new Array()
:创建数组的构造函数Array.from()
参数为一个类数组对象,即任何可迭代的结构Array.of()
可以把一组参数转化为数组,这个方法用于替代在ES6
之前使用的Array.prototype.slice.call(arguments)
console.log(Array.of(1,2,3,4)) // [1,2,3,4]
Array.isArray()
检测参数是否为一个数组- 搜索和位置方法
严格相等搜索 :
indexOf()
lastIndexOf()
includes()
前两个方法在所有版本都可以使用,而第二个方法是
es7
新增的.这些方法都接受两个参数: 要查找的元素和一个可选的起始搜索位置,lastIndexOf()
从后面开始搜索indexOf()
和LastIndexOf()
都要返回查找的元素在数组中的位置,如果没有找到就返回-1
,includes()
返回布尔值,表示是否能找到.每一项都会用(===)比较
断言函数搜索 :
断言函数参数(element,index,array) => Boolean.
- `find()` 返回满足搜索的第一个元素本身
- `findIndex()` 返回满足搜索条件的第一个元素的索引
const persons = [
{name: 'alice', age: 18},
{name: 'bob', age: 20},
{name: 'jery', age: 19},
];
const ageAbove19 = (person) => person.age > 19;
const personFound = persons.find(ageAbove19);
console.log(personFound);
// { name: 'bob', age: 20 }
const personIndexFound = persons.findIndex(ageAbove19);
console.log(personIndexFound); //1
操作方法
concat()
合并多个数组,原数组不变,Symbol.isConcatSpreadable
可以阻止其打平参数数组slice()
参数:(start,end) end不写默认到结尾,截取数组splice()
主要目的是在数组中插入元素,但有三种用法- 删除 :两个参数:要删除的第一个元素的位置和要删除的数量
splice(0,2)
可以删除前两个元素 - 插入:三个参数:开始位置,删除的数量,要插入的元素.比如
splice(2,0,'red','green')
会在位置2插入字符串red green
- 替换: 通用传入三个元素.根据插入的用法删除一个元素替换掉
应用://insert
Array.prototype.insert = function insert(index, ...items) {
this.splice(index, 0, ...items);
return this;
};
//update
Array.prototype.update = function update(index, ...items) {
this.splice(index, 1, ...items);
return this;
};
//remove
Array.prototype.remove = function remove(index, removeCount) {
this.splice(index, removeCount);
return this;
};
- 删除 :两个参数:要删除的第一个元素的位置和要删除的数量
push()
该方法返回被弹出的元素pop()
取出第一个元素,返回被取出的元素shift()
向数组开头添加批量的元素。返回改变后的数组长度。
- 迭代器方法
keys()
返回数组索引的迭代器values()
返回数组元素的迭代器entries()
返回索引/值对的迭代器 ```javascript const colors = [‘red’,’blue’,’green’];
const Keys = Array.from(colors.keys()); const Values = Array.from(colors.values()); const Entries = Array.from(colors.entries());
console.log(Keys); //[ 0, 1, 2 ] console.log(Values); //[ ‘red’, ‘blue’, ‘green’ ] console.log(Entries); // [ [ 0, ‘red’ ], [ 1, ‘blue’ ], [ 2, ‘green’ ] ]
补充 : 在遍历`entries`时可以通过`ES6`的解构
- 迭代方法
1. `forEach() :` 对数组每一项都运行传入的函数,没有返回值.不允许中途 break 或者 continue。
```javascript
let array = [1,2,3];
array.forEach((item) => {
item += 10;
})
console.log(array); // [ 1, 2, 3 ]
注意 :
- `forEach()`不能改变原数组
- `break 和 continue`都可以通过`return`实现
map() :
对数组每一项都运行传入的函数,返回由每次函数调用的结果构成的数组 ```javascript let array = [1,2,3];
let ans = array.map((item) => { return item + 10; })
console.log(ans);
<br />**注意 :** 需要有**返回值**
3. `fiter() :` 检查每个元素是否满足过滤条件,返回满足过滤条件的数组
```javascript
const colors = ['red','blue','green'];
console.log(colors.filter((item) => item.length > 3)); //[ 'blue', 'green' ]
every() :
对每一项都运行传入的函数,如果对每一项函数都返回true
,这这个方法返回true
```javascript //1 const nums = [1, 2, 3];
const isAllNumber = nums.every((num) => typeof num === ‘number’);
console.log(isAllNumber); // true //2 const nums = [1, 2, 3, ‘4’];
const isAllNumber = nums.every((num) => typeof num === ‘number’);
console.log(isAllNumber); //false
5. `some() :`只要有满足条件的就返回`true`
6. `reduce() :`逐个遍历数组元素,每一步都将当前元素的值与上一步的计算结果相加(上一步的计算结果是当前元素之前所有元素的总和)——直到没有更多的元素被相加。
```javascript
const arr = [1,2,3,4];
const ans = arr.reduce((pre,cur) => pre+cur);
console.log(ans); //10
数组扁平化:
- 顺序相关方法
sort()
reverse()
注意:
`reverse()`和`sort()`都返回调用它们的数组的引用
- 实现
deepFlat
**reduce方法**
```javascript const { log } = console;
const arr = [1, [2], [3, [4]], [[[6]]]];
log(arr.flat());
function deepFlat(arr) { return arr.reduce((res,next) => { return res.concat(Array.isArray(next) ? deepFlat(next) : next); },[]) }
log(deepFlat(arr));
- `Es6新方法 : Array.prototype.flat()`
```javascript
let a = [1,[2,3]];
a.flat(); // [1,2,3]
a.flat(1); //[1,2,3]
let a = [1,[2,3,[4,[5]]]];
a.flat(3); // [1,2,3,4,5] a是4维数组
// 若不知道数组维度进行扁平化,可直接使用Infinity,可对任意纬度数组进行扁平化
let a = [1,[2,3,[4,[5]]]];
a.flat(Infinity); // [1,2,3,4,5] a是4维数组
// 若不知道数组维度进行扁平化,可直接使用Infinity,可对任意纬度数组进行扁平化
- 循环 ```javascript const { log } = console;
const arr = [1, [2], [3, [4]], [[[6]]]];
log(arr.flat());
function deepFlat(arr) { let res = []; for(let i = 0 , length = arr.length ; i < length ; i ++) { if(Array.isArray(arr[i])) { res.push(…deepFlat(arr[i])) } else res.push(arr[i]); } return res; }
log(deepFlat(arr));
4. 实现 reduce 方法
```javascript
const { log } = console;
function myReduce(arr, reducer, initialValue) {
let res = initialValue || arr[0];
let startIndex = initialValue ? 0 : 1;
for(let i = startIndex ; i < arr.length; i ++) {
res = reducer(res,arr[i]);
}
return res;
}
log(myReduce([1, 2, 3], (pre, cur) => pre + cur, 10));
- 实现 shuffle 方法
sort()
```javascript const { log } = console;
Array.prototype.shuffle = function() { return this.sort(function(a, b) { return Math.random() > 0.5 ? -1:1 }); }
const nums = [1, 2, 3, 4, 5]; log(nums.shuffle());
2. `Math.random`
```javascript
Array.prototype.shuffle = function () {
const len = this.length;
for (let i = len - 1; i > 0; i--) {
const j = ~~(Math.random() * (i + 1));
[this[i], this[j]] = [this[j], this[i]];
}
return this;
};