内容简介:下面列出了这几个遍历语法规则:在 JavaScript 中所有的数组都是对象,这意味着你可以给数组添加字符串属性:如果打印,那么这个 test 也会被打印出来
基本语法
下面列出了这几个遍历语法规则:
for (let index = 0; index < array.length; index++) { const element = array[index] // ... } array.forEach(element => { // ... }) for (const key in array) { // ... } for (const iterator of array) { // ... }
分情况讨论这几种写法的不同
非数字的属性
在 JavaScript 中所有的数组都是对象,这意味着你可以给数组添加字符串属性:
array = ['a', 'b', 'c'] array.test = 'testing' console.log(array) // [ 'a', 'b', 'c', test: 'testing' ]
如果打印,那么这个 test 也会被打印出来
在浏览器中,使用 console.table(array)
打印这个数组可以看到,这个对象中 test 为 index,testing 为 value;其他数组项的 index 值均为数字
上述提到的几个遍历方法中只有 for-in 循环才能够打印出这个键值对:
for (const key in array) { console.log(array[key]) }
实际应用的问题
通常情况下,不建议使用 for-in 来遍历数组,除非你知道这个数组对象中没有这样的属性
数组空项
假设要遍历的数组张这样: array = ['a', , 'c']
// a undefined c for (let index = 0; index < array.length; index++) { const element = array[index] console.log(element) // 没有跳过空值 } // a c array.forEach(element => { console.log(element) // 跳过空值 }) // a c for (const key in array) { console.log(array[key]) // 跳过空值 } // a undefined c for (const iterator of array) { console.log(iterator) // 没有跳过空值 }
上面几个遍历方法,只有 forEach 和 for-in 遍历会跳过空值,值得注意的是,如果空值明确设置为 undefined 如 ['a', undefined, 'c']
那么所有遍历方法都能够将 undefined 遍历出来
实际应用的问题
在 JSON 中是不支持这样的空值的,如果在 parse 方法调用时传入的 JSON 字符串数据含有空值,会报错:
JSON.parse('["a", , "c"]') // 所以建议使用 for-of 或 for 循环进行遍历,因为如果
- stringify 方法调用时,空值会被转为 null 非空值或 undefined
- 正确的做法应该是保持 undefined,遍历使用 for-of 或 for 循环
建议使用 for-of
方法 this 指向的上下文
在 forEach 中需要传入一个函数,这个函数的 this 指向因语法形式而变化:
for (let index = 0; index < array.length; index++) { const element = array[index] console.log(this) // {} } array.forEach(function (element) { console.log(this) // undefined }) array.forEach(element => { console.log(this) // {} }) for (const key in array) { console.log(this) // {} } for (const iterator of array) { console.log(this) // {} }
上述遍历写法,只有 forEach 在传入非箭头函数的时候会出现不一致的情况
建议使用箭头函数
Async/Await
async 异步编程中 forEach 则不会按照预期执行,如下:
// a undefined c {(async () => { for (const iterator of array) { const result = await new Promise(res => setTimeout(() => { res(iterator) }, 1000)) console.log(result) } })()} // a c {(async () => { for (const key in array) { const result = await new Promise(res => setTimeout(() => { res(array[key]) }, 1000)) console.log(result) } })()} // a undefined c {(async () => { for (let index = 0; index < array.length; index++) { const result = await new Promise(res => setTimeout(() => { res(array[index]) }, 1000)) console.log(result) } })()} // 语法错误 {(async () => { array.forEach(element => { const result = await new Promise(res => setTimeout(() => { res(element) }, 1000)) console.log(result) }) })()}
按照上述写法 forEach 会报错,首先看一下 forEach 的原理:
本质上 forEach 就像一个 for 循环的包装:
Array.prototype.forEach = function (callback) { for (let index = 0; index < this.length; index++) { callback(this[index], index, this) } }
如果按照上述写法,那么在回调函数内部调用 await 需要这个回调函数本身也是 async 函数,因此改为如下写法:
// 语法错误 {(async () => { array.forEach(async element => { const result = await new Promise(res => setTimeout(() => { res(element) }, 1000)) console.log(result) }) })()}
按照这样写法,forEach 最后会变成并行执行,而非串行。
因此建议使用 for-of 循环
或者创建一个 forEachAwait 方法:
async function forEachAwait(arr, cb) { for (let index = 0; index < array.length; index++) { await cb(arr[index], index, arr) } } // a undefined c {(async () => { forEachAwait(array, async (elem) => { const result = await new Promise(res => setTimeout(() => { res(elem) }, 1000)) console.log(result) }) })()}
参考:
欢迎订阅我的公众号:
以上所述就是小编给大家介绍的《一文彻底弄懂 for forEach for-in for-of 的区别》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
perl进阶
Randal L.Schwartz、brian d.foy、Tom Phoenix / 韩雷 / 人民邮电出版社 / 2015-10-1 / 69
本书是Learning Perl一书的进阶。学完本书之后,您可以使用Perl语言的特性编写从简单脚本到大型程序在内的所有程序,正是Perl语言的这些特性使其成为通用的编程语言。本书为读者深入介绍了模块、复杂的数据结构以及面向对象编程等知识。 本书每章的篇幅都短小精悍,读者可以在一到两个小时内读完,每章末尾的练习有助于您巩固在本章所学的知识。如果您已掌握了Learning Perl中的内容并渴......一起来看看 《perl进阶》 这本书的介绍吧!