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

目录
  • 前言
  • 可枚举的属性
    • 可迭代对象
  • 在 forEach 与 map 方法
    • 链式调用
    • 性能
  • 结论

前言

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

(0)

相关推荐

  • js使用for循环及if语句判断多个一样的name

    var items = document.getElementsByName("spec_spec_1[]"); alert(items.length); for (i = 0; i < items.length; i++) { if(items[i].value==''){ alert('名称不能为空'); } }

  • 用循环或if语句从json中取数据示例

    首先,例如json数据如下书写: {"head": [ {"text":"广州","id":"广州","pid":"广东省"}, {"text":"郑州","id":"郑州","pid":"河南省"}], } 如上,倘若想将id和pid数据依次取出,

  • JavaScript中对循环语句的优化技巧深入探讨

    循环是所有编程语言中最为重要的机制之一,几乎任何拥有实际意义的计算机程序(排序.查询等)都里不开循环. 而循环也正是程序优化中非常让人头疼的一环,我们往往需要不断去优化程序的复杂度,却因循环而纠结在时间复杂度和空间复杂度之间的抉择. 在 javascript 中,有3种原生循环,for () {}, while () {}和do {} while (),其中最为常用的要数for () {}. 然而for正是 javascript 工程师们在优化程序时最容易忽略的一种循环. 我们先来回顾一下for

  • Javascript中for循环语句的几种写法总结对比

    前言 for循环我们在js遍历对象或数组时都会有用到了,今天我们一起来看一些关于for循环的一些使用例子了,具体的操作细节如下文介绍. 一般写法如下: for(var i = 0;i< arr.length;i++) { var a = arr[i]; //... } 这就是一个常见的,正序循环的for循环.这样写的缺点大家都明白:每次都从arr里取length与i来对比,浪费性能(而且,要是arr的长度是动态变化的,就会出现死循环).改进这个循环的办法是用变量保存arr.length: for

  • javascript中的循环语句for语句深入理解

    程序实现中经常要用到循环语句,其中for循环是多数语言都有的.在javascript中,for循环有几种不同的使用情况,下面就分别来讲述我的理解. 第一种:(通常情况,循环执行相关操作) 复制代码 代码如下: var objA=document.getElementsByTagName("a"); var i,max; for(i=0,max=objA.length;i<max;i++){ objA[i].onclick=function(){ alert(this.innerH

  • javascript 循环语句 while、do-while、for-in、for用法区别

    前两个唯一的差别就是循环和判断的顺序不同,do-while比while多循环一次,我就不举例了. for循环相信大家也熟的不能再熟了,我们就看for-in这一句. 这个其实是针对数组的,js中数组的初始化也挺奇特的比如我们在script结点里写:(另外注意下数组的初始化,用的是中括号) "); var a=[3,4,5,7]; for(var test in a){ document.write(test+": "+a[test]+""); } -->

  • 简单学习JavaScript中的for语句循环结构

    可以直接看示例,用得太多了,很简单 (function() { for(var i=0, len=demoArr.length; i<len; i++) { if (i == 2) { // return; // 函数执行被终止 // break; // 循环被终止 continue; // 循环被跳过 }; console.log('demo1Arr['+ i +']:' + demo1Arr[i]); } })(); 关于for循环,有一下几点需要注意 for循环中的i在循环结束之后任然存在

  • 详解JavaScript中循环控制语句的用法

    JavaScript提供完全控制来处理循环和switch语句.可能有一种情况,当你需要退出一个循环,但未达到其底部.也可能有一种情况,当要跳过的码块的一部分,并直接开始下一个迭代. 为了处理这些情况下,JavaScript提供了break和continue语句.这些语句是用来马上退出任何循环或启动循环的下一次迭代. break 语句: break语句,这是简单地用switch语句介绍,用于提前退出循环,打破封闭的花括号. 例子: 这个例子说明了如何使用break语句同while循环.请注意循环打

  • JavaScript for循环 if判断语句(学习笔记)

    今天学习了JavaScript里面的for循环以及if的判断语句 for(初始值:循环条件:操作){ 满足条件要执行的代码语句 } 初始值:循环前的初始化变量,通常为赋值表达式:建议用var赋值,可以加快运行速度. 循环条件:每次循环前要计算的条件,是运算符类别中的条件运算符,返回值为true或false,当返回值为true时执行循环,为false时退出循环.(往往是i>=n;或用逻辑运算符) 操作:每循环一次以后要计算的表达式,通常是递增++或递减--等赋值表达式. for语句中的三个参数,第

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

    目录 前言 可枚举的属性 可迭代对象 在 forEach 与 map 方法 链式调用 性能 结论 前言 在 JavaScript 中使用循环时,需要正确定义两个关键内容:可枚举属性(enumerable properties)和可迭代对象(iterable objects). 可枚举的属性 可枚举对象的一个定义特征是,当我们通过赋值运算符将属性赋值给对象时,我们将内部可枚举标志(enumerable)设置为 true.这是默认值. 但是,我们可以通过将其设置为 false 来更改此行为. 经验法

  • 谈谈JavaScript中的垃圾回收机制

    JavaScript 具有自动垃圾收集机制,也就是说,执行环境会负责管理代码执行过程中使用的内存. 在编写 JavaScript 程序时,开发人员不用再关心内存使用问题,所需内存的分配以及无用内存的回收完全实现了自动管理. 这种垃圾收集机制的原理其实很简单:找出那些不再继续使用的变量,然后释放其占用的内存.为此,垃圾收集器会按照固定的时间间隔(或代码执行中预定的收集时间), 周期性地执行这一操作. 具体到浏览器中的实现,则通常有两个策略,分别为标记清除和引用计数. 一.标记清除 JavaScri

  • 谈谈JavaScript中的函数

    JS中的函数简介 JS中的函数是一种通过调用来完成具体业务的一段代码块.最核心的目的是将可重复执行的操作进行封装,然后供调用方无限制的调用. JS中的函数的定义 JS中函数定义,有如下两种形式: 方式1 function f1(){} //函数声明,f1为函数名,可以将其理解为变量f1指向一个函数 function f2(){return 100;}//函数允许有返回值 function f3(a,b){}//函数中可以定义多个参数,无需指定变量类型 方式2 var f4=function(){

  • 详细谈谈MYSQL中的COLLATE是什么

    前言 在mysql中执行show create table <tablename>指令,可以看到一张表的建表语句,example如下: CREATE TABLE `table1` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `field1` text COLLATE utf8_unicode_ci NOT NULL COMMENT '字段1', `field2` varchar(128) COLLATE utf8_unicode_ci

  • 详细讨论JavaScript中的求值策略

    目录 一栗以蔽之 参数传递 按值传递 按共享传递 总结 延伸 - 惰性求值 最近在研究 lambda演算 中的 η-变换 在JavaScript中的应用,偶然在 stackoverflow 上看到一个比较有意思的问题.关于JavaScript的求值策略,问js中函数的参数传递是按值传递还是按引用传递?回答很经典. 一栗以蔽之 function changeStuff(a, b, c) { a = a * 10; b.item = "changed"; c = {item: "

  • 简单谈谈javascript中的变量、作用域和内存问题

    [变量] [1]定义:可变的量,相当于给一个不定的数据起了一个外号.变量是存储信息的容器. [2]特性:js中的变量是松散类型的,可以保存任何类型的数据.它只是在特定时间用于保存特定值的一个名字而已.由于不存在定义某个变量必须要保存何种数据类型值的规则,变量的值及其数据类型可以在脚本的生命周期内改变. [3]变量声明:变量可以在声明时赋值,但不能有其他操作,如+=.-=等 var a = 2;//是正确的 var a += 2;//是错误的 var a = 2++;//是错误的,++只能用于变量

  • 详细讲解JavaScript中的this绑定

    this 可以说是 javascript 中最耐人寻味的一个特性,就像高中英语里各种时态,比如被动时态,过去时,现在时,过去进行时一样,无论弄错过多少次,下一次依然可能弄错.本文启发于<你不知道的JavaScript上卷>,对 javasript 中的 this 进行一个总结. 学习 this 的第一步就是明白 this 既不是指向函数自身也不指向函数的作用域.this 实际上是在函数被调用时发生的绑定,它指向什么地方完全取决于函数在哪里被调用. 默认绑定 在 javascript 中 ,最常

  • 详细分析JavaScript中的深浅拷贝

    在说JS中深浅拷贝之前,我们需要对JS中的数据类型有所了解,分为基本数据类型与引用数据类型,对于基本数据类型并没有深浅拷贝的说法,深浅拷贝主要针对引用数据类型. 一.浅拷贝 浅拷贝只复制了引用,并没有复制值.在JS中最简单的浅拷贝就是利用"="赋值操作符来实现. var obj1 = { a:1, b:[2,3,4], c:{name:'tanj'}, fun:function(){ console.log('fun') } } var obj2 = obj1 obj2.a = 666

  • 谈谈JavaScript中的函数与闭包

    闭包这东西,说难也难,说不难也不难,下面我就以自己的理解来说一下闭包 一.闭包的解释说明 对于函数式语言来说,函数可以保存内部的数据状态.对于像C#这种编译型命令式语言来说,由于代码总是在代码段中执行,而代码段是只读的,因此函数中的数据只能是静态数据.函数内部的局部变量存放在栈上,在函数执行结束以后,所占用的栈被释放,因此局部变量是不能保存的. Javascript采用词法作用域,函数的执行依赖于变量作用域,这个作用域是在定义函数时确定的.因此Javascript中函数对象不仅保存代码逻辑,还必

  • 简单谈谈Javascript中类型的判断

    数据类型的判断有这么几种方式 1.一元运算符 typeOf 2.关系运算符 instanceof 3.constructor 属性 4.prototype属性 一.typeof typeof的返回值有以下几种 类型 结构 Undefined "undefined" Null "object" (见下方) 布尔值 "boolean" 数值 "number" 字符串 "string" Symbol (ECMAS

随机推荐