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

 更新时间:2021年8月23日 00:00  点击:2366

前言

在 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循环差异内容请搜索猪先飞以前的文章或继续浏览下面的相关文章希望大家以后多多支持猪先飞!

[!--infotagslink--]

相关文章

  • 使用PHP+JavaScript将HTML页面转换为图片的实例分享

    这篇文章主要介绍了使用PHP+JavaScript将HTML元素转换为图片的实例分享,文后结果的截图只能体现出替换的字体,也不能说将静态页面转为图片可以加快加载,只是这种做法比较interesting XD需要的朋友可以参考下...2016-04-19
  • 关于JavaScript中name的意义冲突示例介绍

    在昨天的《Javascript权威指南》学习笔记之十:ECMAScript 5 增强的对象模型一文中,对于一段代码的调试出现了一个奇怪现象,现将源代码贴在下面: 复制代码 代码如下: <script type="text/javascript"> function Person(){}...2014-05-31
  • C#和JavaScript实现交互的方法

    最近做一个小项目不可避免的需要前端脚本与后台进行交互。由于是在asp.net中实现,故问题演化成asp.net中jiavascript与后台c#如何进行交互。...2020-06-25
  • javascript自定义的addClass()方法

    复制代码 代码如下: //element:需要添加新样式的元素,value:新的样式 function addClass(element, value ){ if (!element.className){ element.className = value; }else { newClassName = element.className; newClas...2014-05-31
  • JavaScript中的this关键字使用方法总结

    在javascritp中,不一定只有对象方法的上下文中才有this, 全局函数调用和其他的几种不同的上下文中也有this指代。 它可以是全局对象、当前对象或者任意对象,这完全取决于函数的调用方式。JavaScript 中函数的调用有以下...2015-03-15
  • 详解javascript数组去重问题

    首先,我想到的是另建一个结果数组,用来存储原始数组中不重复的数据。遍历原始数组依次跟结果数组中的元素进行比较,检测是否重复。于是乎,我写出了如下代码A: Array.prototype.clearRepetitionA = function(){ var resul...2015-11-08
  • JavaScript中逗号运算符介绍及使用示例

    有一道js面试题,题目是这样的:下列代码的执行结果是什么,为什么? 复制代码 代码如下: var i, j, k; for (i=0, j=0; i<10, j<6; i++, j++) { k = i+j; } document.write(k); 答案是显示10,这道题主要考察JavaScript的逗...2015-03-15
  • javascript的事件触发器介绍的实现

    事件触发器从字面意思上可以很好的理解,就是用来触发事件的,但是有些没有用过的朋友可能就会迷惑了,事件不是通常都由用户在页面上的实际操作来触发的吗?这个观点不完全正确,因为有些事件必须由程序来实现,如自定义事件,jQue...2014-06-07
  • Javascript类型转换的规则实例解析

    这篇文章主要介绍了Javascript类型转换的规则实例解析,涉及到javascript类型转换相关知识,对本文感兴趣的朋友一起学习吧...2016-02-27
  • ActiveX控件与Javascript之间的交互示例

    1、ActiveX向Javascript传参 复制代码 代码如下: <script language="javascript" for="objectname" event="fun1(arg)"> fun2(arg); </script> objectname为ActiveX控件名,通过<object>标签里的id属性设定,如下; 复制...2014-06-07
  • 详解JavaScript操作HTML DOM的基本方式

    通过 HTML DOM,可访问 JavaScript HTML 文档的所有元素。 HTML DOM (文档对象模型) 当网页被加载时,浏览器会创建页面的文档对象模型(Document Object Model)。 HTML DOM 模型被构造为对象的树: 通过可编程的对象模型,Java...2015-10-23
  • JavaScript获取浏览器信息的方法

    Window有navigator对象让我们得知浏览器的全部信息.我们可以利用一系列的API函数得知浏览器的信息.JavaScript代码如下:function message(){ txt = "<p>浏览器代码名: " + navigator.appCodeName + "</p>";txt+= "<p>...2015-11-24
  • mysql中获取一天、一周、一月时间数据的各种sql语句写法

    创建表:复制代码 代码如下:create table if not exists t( id int, addTime datetime default '0000-00-00 00:00:00′)添加两条初始数据:insert t values(1, '2012-07-12 21:00:00′);insert t values(2, '2012-07...2014-05-31
  • JavaScript预解析,对象详解

    这篇文章主要介绍了JavaScript预解析,对象的的相关资料,小编觉得这篇文章写的还不错,需要的朋友可以参考下,希望能够给你带来帮助...2021-11-10
  • 学习JavaScript设计模式之装饰者模式

    这篇文章主要为大家介绍了JavaScript设计模式中的装饰者模式,对JavaScript设计模式感兴趣的小伙伴们可以参考一下...2016-01-21
  • Java8处理List的双层循环问题

    这篇文章主要介绍了Java8处理List的双层循环问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-19
  • 跟我学习javascript的最新标准ES6

    虽然ES6都还没真正发布,但已经有用ES6重写的程序了,各种关于ES789的提议已经开始了,这你敢信。潮流不是我等大众所能追赶的。潮流虽然太快,但我们不停下学习的步伐,就不会被潮流丢下的,下面来领略下ES6中新特性,一堵新生代JS...2015-11-24
  • javascript设计模式之解释器模式详解

    神马是“解释器模式”?先翻开《GOF》看看Definition:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。在开篇之前还是要科普几个概念: 抽象语法树: 解释器模式并未解释如...2014-06-07
  • JavaScript学习笔记整理_setTimeout的应用

    下面小编就为大家带来一篇JavaScript学习笔记整理_setTimeout的应用。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2016-10-03
  • jquery中常用的SET和GET$(”#msg”).html循环介绍

    复制代码 代码如下: $(”#msg”).html(); //返回id为msg的元素节点的html内容。 $(”#msg”).html(”new content“); //将“new content” 作为html串写入id为msg的元素节点内容中,页面显示粗体的new content $(”...2013-10-13