详细谈谈JavaScript中循环之间的差异


Posted in Javascript onAugust 23, 2021

前言

在 JavaScript 中使用循环时,需要正确定义两个关键内容:可枚举属性(enumerable properties)和可迭代对象(iterable objects)。

可枚举的属性

可枚举对象的一个定义特征是,当我们通过赋值运算符将属性赋值给对象时,我们将内部可枚举标志(enumerable)设置为 true。这是默认值。

但是,我们可以通过将其设置为 false 来更改此行为。

经验法则是,可枚举属性总是出现在 for...in 循环中。

让我们看看这一点:

const users = {}
users.languages = 'JavaScript'
​
Object.getOwnPropertyDescriptor(users, 'languages')
// output -> { value: 'JavaScript', writable: true, enumerable: true, configurable: true }
​
// 在循环中对我们使用的属性进行更多的控制
Object.defineProperty(users, 'role', { value: 'Admin', writable: true, enumerable: false })
​
for (const item in users) {
  console.log(item) // languages
}

可以看到,我们为 users 变量添加了一个 languages 属性,使用 Object.getOwnPropertyDescriptor 方法输出 languages 属性描述符的 enumerable 属性为 true。

使用 Object.defineProperty 为添加 role 属性,并将 enumerable 设置为 false,在 for...in 循环中并没有输出 role 属性。即 for...in 循环中的属性为可枚举属性。

可迭代对象

如果一个对象定义了它的迭代行为,那么它是可迭代的。在本例中,将在 for...of 构造中循环的值将定义其迭代行为。可迭代的内置类型包括 Array、String、Set 和 Map 对象不可迭代,因为它没有指定 @iterator 方法。

基本上,在 JavaScript 中,所有可迭代对象都是可枚举对象,但并非所有可枚举对象都是可迭代对象。

这里有一种概念化的方法:for...in 查找数据中的对象,而 for...of 查找重复序列。

让我们看看这一切在与 Array 数据类型一起使用时的效果:

const languages = ['JavaScript', 'Python', 'Go']
​
// 与 for...in 循环一起使用
for (const language in languages) {
  console.log(language)
}
// output
// 0
// 1
// 2
​
// 与 for...of 循环一起使用
for (const language of languages) {
  console.log(author)
}
// output -> JavaScript Python Go

在使用这种构造时,需要牢记的一点是,如果调用了 typeof,并且输出为 object,那么您可以使用 for...in 循环。

让我们看看这个对 languages 变量的操作:

typeof languages // "object" -> 因此我们可以在中使用 for

乍一看,这可能令人惊讶,但需要注意的是,数组是一种特殊类型的对象,以索引为键。知道 for...in 将在构造中查找对象可以极大地帮助我们。当 for...in 循环找到一个对象时,它将在每个键上循环。

我们可以将 for ..in 循环在 languages 数组上的方式可视化如下:

const languages = {
  0: 'JavaScript',
  1: 'Python',
  2: 'Go'
}

注意:如果它可以被追踪到一个对象(或者从对象原型链继承它),for...in 将以没有特定顺序遍历键。

同时,如果它实现了一个迭代器 for.. of 构造,它将在每次迭代中循环遍历该值。

在 forEach 与 map 方法

虽然 forEach 和 map 方法可以用来实现相同的目标,但它们的行为和性能特性有所不同。

在基本级别,当函数被调用时,它们都会接收一个回调作为参数。

考虑以下片段:

const scoresEach = [2, 4 ,8, 16, 32]
const scoresMap = [2, 4 ,8, 16, 32]
const square = (num) => num * num

让我们详细介绍一下它们在操作上的一些差异。

forEach 返回 undefined,而 map 返回一个新的 array:

let newScores = []
const resultWithEach = scoresEach.forEach(score => {
  const newScore = square(score)
  newScores.push(newScore)
})
​
const resultWithMap = scoresMap.map(square)
​
console.log(resultWithEach) // undefined
console.log(resultWithMap) // [4, 16, 64, 256, 1024]

Map 是一个纯函数,同时 forEach 执行一些突变:

console.log(newScores) // [4, 16, 64, 256, 1024]

在我看来,map 支持函数式编程范式。我们不必总是执行突变来获得期望的结果,不像 forEach,我们必须突变 newScores 变量。在每次运行时,当提供相同的输入时,map 函数将产生相同的结果。同时,forEach 对应项将从上一个突变的先前值中提取。

链式调用

使用 map 可以进行链式调用,因为返回的结果是一个数组。因此,可以对结果立即调用任何其他数组方法。换句话说,我们可以调用 filter、reduce、some 等方法。这在 forEach 中是不可能的,因为返回的值为 undefined 的。

性能

map 方法的性能往往优于 forEach 方法。

检查使用 map 和 forEach 实现的等效代码块的性能。平均而言,您将看到 map 函数的执行速度至少快 50%。

结论

在上面讨论的所有循环结构中,给我们最多控制的是 for..of 循环。我们可以将其与关键字 return、continue 和 break 一起使用。这意味着我们可以指定对数组中的每个元素要发生什么,以及是否要提前离开或跳过。

到此这篇关于JavaScript中循环之间差异的文章就介绍到这了,更多相关JavaScript循环差异内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
关于__defineGetter__ 和__defineSetter__的说明
May 12 Javascript
JavaScript极简入门教程(二):对象和函数
Oct 25 Javascript
vue2.0的contextmenu右键弹出菜单的实例代码
Jul 24 Javascript
详解如何去除vue项目中的#——History模式
Oct 13 Javascript
ES6/JavaScript使用技巧分享
Dec 14 Javascript
JavaScript继承与多继承实例分析
May 26 Javascript
详解JavaScript中的函数、对象
Apr 01 Javascript
vue中created和mounted的区别浅析
Aug 13 Javascript
基于JavaScript实现十五拼图代码实例
Apr 26 Javascript
element-ui中dialog弹窗关闭按钮失效的解决
Sep 22 Javascript
JS+CSS实现过渡特效
Jan 02 Javascript
Vue3.0 手写放大镜效果
Jul 25 Vue.js
javascript代码简写的几种常用方式汇总
Aug 23 #Javascript
vue使用Google Recaptcha验证的实现示例
Vue鼠标滚轮滚动切换路由效果的实现方法
Aug 04 #Vue.js
关于React Native使用axios进行网络请求的方法
Aug 02 #Javascript
vscode中使用npm安装babel的方法
Element实现动态表格的示例代码
JavaScript分页组件使用方法详解
You might like
全国FM电台频率大全 - 23 四川省
2020/03/11 无线电
PHP去掉从word直接粘贴过来的没有用格式的函数
2012/10/29 PHP
php中json_encode UTF-8中文乱码的更好解决方法
2014/09/28 PHP
php+html5基于websocket实现聊天室的方法
2015/07/17 PHP
PHP实现的构造sql语句类实例
2016/02/03 PHP
PHP中模糊查询并关联三个select框
2017/06/19 PHP
PHP魔术方法之__call与__callStatic使用方法
2017/07/23 PHP
PHP针对伪静态的注入总结【附asp与Python相关代码】
2017/08/01 PHP
Laravel 5.4前后台分离,通过不同的二级域名访问方法
2019/10/13 PHP
jQuery实现Tab菜单滚动切换的方法
2015/09/21 Javascript
移动适配的几种方案(三种方案)
2016/11/25 Javascript
jQuery树插件zTree使用方法详解
2017/05/02 jQuery
vue 父组件给子组件传值子组件给父组件传值的实例代码
2019/04/15 Javascript
js 闭包深入理解与实例分析
2020/03/19 Javascript
python解决方案:WindowsError: [Error 2]
2016/08/28 Python
python sys,os,time模块的使用(包括时间格式的各种转换)
2018/04/27 Python
Python学习小技巧总结
2018/06/10 Python
python实现对csv文件的列的内容读取
2018/07/04 Python
python画柱状图--不同颜色并显示数值的方法
2018/12/13 Python
Python基于Logistic回归建模计算某银行在降低贷款拖欠率的数据示例
2019/01/23 Python
使用Python进行体育竞技分析(预测球队成绩)
2019/05/16 Python
python 多线程对post请求服务器测试并发的方法
2019/06/13 Python
Pycharm-community-2020.2.3 社区版安装教程图文详解
2020/12/08 Python
HTML5实现分享到微信好友朋友圈QQ好友QQ空间微博二维码功能
2018/01/03 HTML / CSS
香蕉共和国Banana Republic官网:美国GAP旗下偏贵族风格服饰品牌
2016/11/21 全球购物
Peter Alexander新西兰站:澳大利亚领先的睡衣设计师品牌
2016/12/10 全球购物
英国家庭和商业健身器材购物网站:Fitness Options
2018/07/05 全球购物
2013年保送生自荐信格式
2013/11/20 职场文书
大学生村官工作感言
2014/01/10 职场文书
大学生应聘求职信
2014/05/26 职场文书
淘宝店策划方案
2014/06/07 职场文书
JS实现简单控制视频播放倍速的实例代码
2021/04/18 Javascript
go:垃圾回收GC触发条件详解
2021/04/24 Golang
Java使用httpRequest+Jsoup爬取红蓝球号码
2021/07/02 Java/Android
CSS布局之浮动(float)和定位(position)属性的区别
2021/09/25 HTML / CSS
Nginx动静分离配置实现与说明
2022/04/07 Servers