10. Array API
- 类数组对象,可迭代对象,数组之间的区别?
- 类数组对象:
格式与数组结构类似,用于length,可以通过索引来访问或者修改里面的元素,但不能书用数组的方法
- 类数组对象:
类数组对可以通过Array.from()来转换成数组,需要有length属性来控制数组长度
注意:
1. 解析`length`时会使用`parseInt()`进行转换,默认为02. 如果`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 - 替换: 通用传入三个元素.根据插入的用法删除一个元素替换掉
应用://insertArray.prototype.insert = function insert(index, ...items) {this.splice(index, 0, ...items);return this;};//updateArray.prototype.update = function update(index, ...items) {this.splice(index, 1, ...items);return this;};//removeArray.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。```javascriptlet 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() :` 检查每个元素是否满足过滤条件,返回满足过滤条件的数组```javascriptconst 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() :`逐个遍历数组元素,每一步都将当前元素的值与上一步的计算结果相加(上一步的计算结果是当前元素之前所有元素的总和)——直到没有更多的元素被相加。```javascriptconst 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()````javascriptlet 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 方法```javascriptconst { 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````javascriptArray.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;};
