迭代的起源:工厂函数Iterator
- 可迭代协议:要想实现可迭代,就必须实现Iterator接口,必须暴露一个属性作为“默认迭代器”,而且这个属性必须使用特殊的
Symbol.iterator作为键。 - 好在js已经在以下数据类型中为我们实现了Iterator接口
- 字符串
- 数组
- 映射
- 集合
- arguments对象
- NodeList等DOM集合类型 注意!对象并未实现Iterator接口,但对象可通过Object.getOwnPropertyDescriptor(对象, 键名)来获取该对象某个属性的描述对象,该描述对象中有一个属性为enumerable,当该属性为true时,下述操作将忽略掉当前键
- for...in循环
- Object.keys()
- JSON.stringify()
- Object.assign()
- 实现了Iterator接口之后我们就可以通过下述方法遍历对应的数据类型了
- for-of 循环
- 数组解构
- 扩展操作符
- Array.from()
- 创建集合
- 创建映射
- Promise.all()接收由期约组成的可迭代对象
- Promise.race()接收由期约组成的可迭代对象
- yield*操作符,在生成器中使用
数组
一、for、for...of
1. for
- 遍历数组
2. for...of(es6引入)
- 部署了Symbol.iterator属性就被视为有iterator接口,就可以使用for...of进行遍历
- for...of可结合keys()、values()、entries()对数组进行遍历,获取键、值、键值对
// for...of遍历数组 let arr = [4, 5, 6] for (let [index, value] of arr.entries()) { console.log(index, value) } // for...of遍历对象 let obj = {a: 1, b: 2} for (let [key, value] of Object.entries(obj)) { console.log(key, value) } // !!!不使用for...of直接用Object.entries也可实现
⭐二、es5中的一些方法
forEach()、reduce()、filter()、map()、every()、some()
1. forEach()
- (1)用途:遍历数组,对数组中的每个元素执行一遍参数方法
- (2)参数
- callback必填
- item:当前元素
- index:当前元素的索引
- array:当前数组
- thisArg可选
- callback必填
- (3)特点
- 一旦开始遍历,就无法退出,即所有元素都会被遍历
- 返回值为undefined
- 不可链式调用
- (4)代码
let arr = [1, 2, 3, 4] arr.forEach(item => { console.log(item) })
2. reduce()
- (1)用途:为每一个元素执行一个callback函数
- (2)参数
- callback必填
- prev:上一个循环中return的值(常用)
- currentValue:当前元素值(常用)
- currentIndex:当前元素的索引
- array:当前数组
- initialValue初始值可选
- callback必填
- (3)代码
// 将数组转为对象并用数组中的id作为新对象的key let arr = [{id: 1, name: 'a'}, {id: 2, name: 'b'}] let obj = arr.reduce((prev, currentValue) => { prev[currentValue.id] = currentValue return prev }, {}) console.log(obj)
3. filter()
- (1)用途:创建一个新数组,包含通过callback函数的所有元素
- (2)参数
- callback回调函数必填
- item:当前元素值
- index:当前元素索引
- array:当前数组
- thisArg可选
- callback回调函数必填
- (4)返回值:一个由通过callback函数的元素组成的新数组,如果没有任何元素通过,则返回[]
- (3)代码
排除小于十的值 function f(arr) { return arr.filter(item => item > 10) } console.log(f([1, 2, 3, 4, 10, 11, 23, 43]))
4. map()
- (1)用途:创建一个新数组,新数组的元素是原来的数组执行callback函数之后的值
- (2)参数
- callback回调函数必填
- item:当前元素值
- index:当前元素索引
- array:当前数组
- thisArg可选
- callback回调函数必填
- (3)代码
// [{key: **, value: ''}, {key: **, value: ''}] → [{**: '', **: ''}] function format(arr) { return arr.map(item => { let obj = {} obj[item.id] = item.name return obj }) } console.log(format([{id: 1, name: 'wang'}, {id: 2, name: 'li'}]))
5. every()
- (1)用途:测试数组中的每一个元素通过callback函数后是否为truth值,返回一个布尔值,如果全部通过返回true,否则返回false
- (2)参数
- callback回调函数必填
- item:当前元素值
- index:当前元素索引
- array:当前数组
- thisArg可选
- callback回调函数必填
- (3)特点:不会改变原数组
- (4)代码
[1, 2, 4, 11, 34, 23].every(item => item > 10) // false
6. some()
- (1)用途:测试数组中任意一个元素通过callback函数后是否为truth值,返回一个布尔值,如果由一个通过,返回true,全部不通过则返回false
- (2)参数
- callback回调函数必填
- item:当前元素值
- index:当前元素索引
- array:当前数组
- thisArg可选
- callback回调函数必填
- (3)特点:不会改变原数组
- (4)代码
[1, 2, 3, 4, 11, 34, 23].some(item => item > 10) // true
⭐三、es6中的一些方法
keys()、values()、entries()
// 结合for...of遍历数组
let arr = [1, 3, 5, 7, 9]
for (let [index, value] of arr.entries()) {
console.log(index, value)
}
// 使用遍历器的next方法
let arr = [1, 2, 3, 4]
let entries = arr.entries()
console.log(entries.next()) // {value: [0, 1], done: false}
console.log(entries.next()) // {value: [1, 2], done: false}
...
console.log(entries.next()) // {value: undefined, done: true}
对象
一、for...in
- 遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)
- 缺点:只能获取键名不能获取键值
let obj = {a: '1', b: '2'}
for (let key in obj) {
console.log(`${key}: ${obj[key]}`)
}
二、es6新增的keys()、values()、entries()
// 结合for...of遍历对象
let obj = {name: 'li', age: 18}
for (let [key, value] of Object.entries(obj)) {
console.log(key, value)
}
// 直接使用:返回一个数组
let obj = {name: 'zhang', age: 20}
Object.entries(obj)
// [[name, 'zhang'], [age, 20]]
三、Object.getOwnPropertyNames(对象)
let obj = {name: 'zhang', age: 20}
Object.getOwnPropertyNames(obj).forEach(key => console.log(key, obj[key]))
// name zhang
// age 20