当前位置:网站首页>请讲一讲JS中的 for...in 与 for...of (下)
请讲一讲JS中的 for...in 与 for...of (下)
2022-08-11 01:26:00 【lovetomato1106】
start
- 上一篇文章学习了一下 for…in;
- 这篇文章就来学习一下 for…of ;
- 以及总结一下两者的差异;
起因
正所谓日有所思夜有所梦,时常梦到for...of。
起因是之前阅读过阮一峰老师的《ECMAScript 6 入门》,当时看到过这么一段内容如下图:ECMAScript 6 入门-18.Iterator 和 for…of 循环 原文链接
当初理解的不透彻,今天再来学习一下。

初步认识
先看看MDN的解释
MDN 的解释:
for…of 语句在可迭代对象(包括 Array,Map,Set,String,TypedArray,arguments 对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句
思考:
可迭代对象
什么是可迭代对象? 它这里例举了一些可迭代对象(Array,Map,Set,String,TypedArray,arguments 对象等)
MDN 中是这样说:要成为可迭代对象, 一个对象必须实现 @@iterator 方法。这意味着对象(或者它原型链上的某个对象)必须有一个键为 @@iterator 的属性,可通过常量 Symbol.iterator 访问该属性;
《ECMAScript 6 入门》中是这样说:一个数据结构只要部署了 Symbol.iterator 属性,就被视为具有 iterator 接口,就可以用 for…of 循环遍历它的成员。
打印一下 MDN 列举的那些可迭代对象,看它说的是否准确。(暂时就已数组为例)
验证
这里我偷个懒,直接打印 Symbol.iterator 属性。
// Array
var arr = [1, 2]
console.log(arr[Symbol.iterator])
// Map
var m = new Map()
console.log(m[Symbol.iterator])
// Set
var set = new Set()
console.log(set[Symbol.iterator])
// String
var str = '你好'
console.log(str[Symbol.iterator])
// TypedArray
var typeArr = new Uint8Array([0x00, 0xff])
console.log(typeArr[Symbol.iterator])
// arguments
;(function () {
console.log(arguments[Symbol.iterator])
})(1, 2, 3)
/* [Function: values] [Function: entries] [Function: values] [Function: [Symbol.iterator]] [Function: values] [Function: values] */
Symbol.iterator 属性
for…of 整个逻辑就是借助属性Symbol.iterator指向的函数。
这个函数执行后会返回一个对象;
返回的对象有 next 方法,每执行一次会返回一个对象;
例如{value: 10, done: false}
演示一下:
var arr = [1, 2, 3, 4]
let fn = arr[Symbol.iterator]()
console.log(fn.next())
console.log(fn.next())
console.log(fn.next())
console.log(fn.next())
console.log(fn.next())
console.log(fn.next())
/* { value: 1, done: false } { value: 2, done: false } { value: 3, done: false } { value: 4, done: false } { value: undefined, done: true } { value: undefined, done: true } */
为了更好理解:我这里重写一下数组的 Symbol.iterator 属性
var arr = [1, 2, 3, 4, 5]
arr[Symbol.iterator] = function () {
const self = this
let index = 0
return {
next() {
if (index < self.length) {
return {
value: self[index++] + '额外加工一下遍历的数据',
done: false,
}
}
return {
value: undefined, done: true }
},
}
}
console.log(arr) // [ 1, 2, 3, 4, 5, [Symbol(Symbol.iterator)]: [Function] ]
for (const i of arr) {
console.log(i)
}
/* 1额外加工一下遍历的数据 2额外加工一下遍历的数据 3额外加工一下遍历的数据 4额外加工一下遍历的数据 5额外加工一下遍历的数据 */
为什么对象没有属性 Symbol.iterator
for…of 遍历对象的时候会报错:Uncaught TypeError: obj is not iterable
原因:
摘抄自 《ECMAScript 6 入门》
对象(Object)之所以没有默认部署 Iterator 接口,是因为对象的哪个属性先遍历,哪个属性后遍历是不确定的,需要开发者手动指定。本质上,遍历器是一种线性处理,对于任何非线性的数据结构,部署遍历器接口,就等于部署一种线性转换。不过,严格地说,对象部署遍历器接口并不是很必要,因为这时对象实际上被当作 Map 结构使用,ES5 没有 Map 结构,而 ES6 原生提供了。
调用 Iterator 接口的场合
- 数组和 Set 的解构赋值
- 扩展运算符
- for…of
- Array.from()
- Map(), Set(), WeakMap(), WeakSet()(比如 new Map([[‘a’,1],[‘b’,2]]))
- Promise.all()
- Promise.race()
for…of 与 for…in 的区别
无论是 for…in 还是 for…of 语句都是迭代一些东西。它们之间的主要区别在于它们的迭代方式。
for…in 语句以任意顺序迭代对象的可枚举属性。
for…of 语句遍历可迭代对象定义要迭代的数据。
还有一个区别这里提一下,for…in 是 ES3 实现的,而 for…of 是 ES6 实现的,所以 for…of 在生产环境使用的时候大概率会被 babel 转换。
end
- 写到这里,对这两个方法有一个初步的认知;
- 其实也没必要说死记硬背:for…in 可以遍历什么,for…of 不能遍历什么。知道迭代的原理,比较好理解;
边栏推荐
猜你喜欢
随机推荐
networkmanager无法打开
Data Filters in ABP
使用mysql语句操作数据表(table)
阿里的数据同步神器——Canal
两日总结九
QT+VTK+PCL拟合圆柱并计算起始点、中止点
导入数据包上传宝贝提示“类目不能为空”是什么原因,怎么解决?
php 判断数组是否为多维数组
Construction inspection, no rules and no square
Apache Commons Configuration远程代码执行漏洞(CVE-2022-33980)分析&复现
std::format格式化自定义类型
Ambari Migrates Spark2 to Other Machines (Graphic and Text Tutorial)
Single-chip human-computer interaction--matrix key
Successfully resolved raise TypeError('Unexpected feature_names type')TypeError: Unexpected feature_names type
R language multiple linear regression, ARIMA analysis of the impact of different candidates in the United States on the economic GDP time series
【21天学习挑战赛】折半插入排序
构建资源的弹性伸缩
The concept of services
22、库存服务
【ASM】字节码操作 ClassWriter COMPUTE_FRAMES 的作用 与 visitMaxs 的关系









