深入学习循环中的let

for循环中let的作用域问题 let中for循环的作用域问题 今天在学习闭包的时候使用var声明的for循环 阅读详情

let 和 const的特性

1.不会被提升

  console.log(a) // Uncaught ReferenceError: Cannot access 'a' before initialization
  console.log(b) // Uncaught ReferenceError: Cannot access 'b' before initialization
  let a = 1
  const b =2

2.不可重复声明

  var a = 1
  const a = 2 // Uncaught SyntaxError: Identifier 'a' has already been declared
  var b = 1
  let b = 2 // Uncaught SyntaxError: Identifier 'b' has already been declared

3.不绑定全局作用域

  let a = 1;
  const b = 2
  console.log(window.a); // undefined
  console.log(window.b); // undefined

拓展延申(开发中,要知道不绑定全局作用域就够了,有兴趣的可以研究下拓展部分)
问:既然不绑定在window上,那它们究竟绑定在哪呢?
要想知道答案,得先了解JS的词法环境,可以参考这篇文章,下面引用别人的一段话来稍作解释

ES6 开始,有别于全局环境记录,有一个单独的声明环境记录,它关联一个词法环境对象 (Lexical Environment Object) 来存储那些不是通过 var function 关键字进行的标识符声明,并且它们都是不可见的。

简而言之

  • var和function变量的声明和保存是在变量环境组件中的,即VariableEnvironment
  • let和const变量的声明和保存以及外部环境引用是在词法环境组件中的,即LexicalEnvironment

4.只在代码块内有效

  {
    var a = 0;
    let b = 1;
  }
  console.log(a) // 0
  console.log(b) // Uncaught ReferenceError: b is not defined

经典for循环

  var arr = []
  for (var i = 0; i < 5; i++) {
    arr[i] = function () {
      console.log(i)
    }
  }
  arr[3]();  // 打印结果:5

因为var声明的变量,会被提升,上面的代码等价于下面的代码,变量i在循环结束后被赋值为5

  var arr = []
  var i
  for (i = 0; i < 5; i++) {
    arr[i] = function () {
      console.log(i)
    }
  }
  arr[3]();  // 打印结果:5

想要输出结果为3的话,ES6的let为此问题提供了解决方法

  var arr = []
  for (let i = 0; i < 5; i++) {
    arr[i] = function () {
      console.log(i)
    }
  }
  arr[3]();  // 打印结果:3

那为什么let它就能解决呢?
一个被提到的比较多的原因是,let变量不提升,可就算不提升,最后i还是变成5,输出也应该是5啊?!!

很多文章中都对这一问题有过解答

如果要追究这个问题,就要抛弃掉之前所讲的这些特性!这是因为 let 声明在循环内部的行为是标准中专门定义的,在早期的 let 实现中本就不包含这一行为,后来专门为这一问题加入这一行为

既然是专门定义的,就肯定有其特殊之处,那特殊在哪呢?

在 for 循环中使用 let 和 var,底层会使用不同的处理方式。
那么当使用 let 的时候底层到底是怎么做的呢?
简单的来说,就是在 for (let i = 0; i < 3; i++) 中,即圆括号之内建立一个隐藏的作用域
然后每次迭代循环时都创建一个新变量,并以之前迭代中同名变量的值将其初始化。

这样对于下面这样一段代码

  var arr = []
  for (let i = 0; i < 5; i++) {
    arr[i] = function () {
      console.log(i)
    }
  }
  arr[3]();  // 打印结果:3

就相当于:

// 伪代码
(let i = 0) {
    arr[0] = function() {
        console.log(i)
    };
}

(let i = 1) {
    arr[1] = function() {
        console.log(i)
    };
}

(let i = 2) {
    arr[2] = function() {
        console.log(i)
    };
};

当执行函数的时候,根据词法作用域就可以找到正确的值,其实你也可以理解为 let 声明模仿了闭包的做法来简化循环过程。

Ubuntu下安装Hive3.1.2教程(附MySQL安装方法及安装包) 文章目录前言一、安装Hive1. 下载压缩包并解压2. 安装Hive3. 配置环境变量4. 修改配置文件二、MySQL安装与配置1. 安装MySQL2. 安装MySQL jdbc包3. 为Hive创建MySQL账号三、验证Hive安装及错误处理1. 启动Hadoop2. 启动hive3. 运行Hive实例总结 前言 Hive 的安装需要建立在 Hadoop 的之上(类似于Hbase),关于 Hadoop 的单机安装以及伪分布式安装可以参考作者的另两篇博客: Ubuntu下单机安装Hadoop详细教程(附 阅读详情

相关推荐

LabVIEW多设备采集实战:1个程序同时控制3个RS485 Modbus仪表

本文详细介绍了如何使用LabVIEW实现多设备RS485 Modbus同步采集,涵盖硬件架构设计、多线程通信框架搭建、数据帧解析技巧及性能优化策略。通过实际项目案例,展示如何解决端口冲突、数据解析错误等工业自动化常见问题,提升采集系统实时性与可靠性。

qsc901234的博客 302

let for循环

在for循环表达式中使用let声明表达式变量 因为let有自己的作用域块,所以在for循环表达式中使用let其实就等价于在代码块中使用let,也就是说 for( let i = 0; i< 5; i++) 这句话的圆括号之间,有一个隐藏的作用域 for( let i = 0; i< 5; i++) { 循环体 } 在每次执行循环体之前,JS 引擎会把 i 在循环体的上下文中重新声明及初始化一次。 var liList = document.querySelectorAll('li') // 共

qq_45178972的博客 3497

激光雷达-IMU标定工具lidar_imu_calib保姆级教程(VLP-16实测)

本文提供激光雷达与IMU联合标定的详细实战教程,重点解析lidar_imu_calib工具在VLP-16上的应用。从环境部署、数据采集技巧到参数配置与结果验证,手把手指导完成标定全流程,并详解如何在LIO-SAM等SLAM系统中应用标定结果,确保传感器融合精度。

food6的博客 475

var和let的循环案例--关于作用域问题

首先,var声明的变量是函数作用域或全局作用域的,而let是块级作用域的。在for循环中使用var时,变量j实际上会被提升到循环外部的函数或全局作用域中,,而setTimeout中的回调函数是在循环结束后才执行的,此时j的值已经变成了3,所以三次回调都输出3。而使用let时,每次循环都会创建一个新的块级作用域,变量k在每次迭代中都是一个新的绑定,即每个setTimeout回调捕获的是该次迭代时的k值。因此,当回调执行时,每个回调都有自己的k值,分别是0、1、2,所以输出0 1 2。

weixin_42017221的博客 281

Windows Server 2012评估版过期自动关机问题:两种高效解决方案详解

本文针对Windows Server 2012评估版过期导致的自动关机问题,提供了两种高效解决方案。一是通过slmgr.vbs命令重置授权,临时延长评估期;二是使用DISM工具将评估版转换为正式版,一劳永逸。文章详细解析了两种方法的操作步骤、注意事项及适用场景,帮助用户快速恢复服务器稳定运行。

pytorchlight8的博客 1195

Intel Realsense windows安装与入门

realsense400系列介绍: https://www.intelrealsense.com/stereo-depth/?utm_source=intelcom_website&utm_medium=button&utm_campaign=day-to-day&utm_content=D400_learn-more_button realsense 435i介绍: ...

hanshuning的专栏 1万+

let、var循环区别

i < 10;i++){return ii < 10;i++){return i。

lianzhenxia的专栏 317

Ubuntu20.04 高效安装企业微信的完整指南

本文提供了在Ubuntu20.04系统上高效安装企业微信的完整指南,详细介绍了通过Deepin-wine环境运行Windows版企业微信的步骤和优化技巧。内容包括系统环境检查、依赖安装、企业微信包的获取与安装、首次运行配置及常见问题解决方案,帮助开发者在Ubuntu系统中流畅使用企业微信进行办公通讯。

weixin_42568801的博客 353

javascript基础从小白到高手系列三:for 循环中的let 声明

每个setTimeout 引用的都是不同的变量实例,所以console.log 输出的是我们期望的值,也就是循。而在使用let 声明迭代变量时,JavaScript 引擎在后台会为每个迭代循环声明一个新的迭代变量。这种每次迭代声明一个独立变量实例的行为适用于所有风格的for 循环,包括for-in 和for-of。不过,如果你只想用const 声明一个不会被修改的for 循环变量,那也是可以的。之所以会这样,是因为在退出循环时,迭代变量保存的是导致循环退出的值:5。

wanmeijuhao的博客 641

Vercel静态站被墙别慌!手把手教你用Cloudflare免费CDN+域名解析搞定DNS污染

本文详细介绍了如何利用Cloudflare免费CDN和域名解析解决Vercel静态网站遭遇DNS污染的问题。通过诊断DNS污染、设计Cloudflare解决方案架构、实战配置步骤以及高级调优技巧,帮助用户快速恢复站点访问并提升防护能力。

weixin_27442001的博客 677

【功能安全】【AutoSAR】程序流监控机制

目录 一、程序流执行的常见故障 二、程序流的监控机制 1、监控功能的实现 2、三种监督机制 a、生命监测机制 b、截止时间监测机制 c、逻辑程序流监测机制 一、程序流执行的常见故障 与程序流相关的故障,在ISO26262中第六章附录D中定义如下: — 执行阻塞; — 死锁; — 活锁; — 执行时间的不正确分配; — 软件要素间的不正确同步。 二、程序流的监控机制 1、监控功能的实现 AutoSAR中对程序流的监控功能的实现主要有“看门狗”栈(Watchdog Stack).

专注汽车软件开发、AutoSAR、车载以太网、SOA、EE架构。 4519

关于 let 在 for 循环中的理解

  每次阅读ECMAScript 6 入门 时,关于其中的一块代码,总是不能很好的理解。如下 var a = []; for (let i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[6](); // 6   与之对应的 如果使用 var 定义变...

weixin_30355437的博客 652

三菱MC协议(MC/TCP):避坑指南|C#实现三菱MC协议:软元件(X/Y/M/D)读写与帧格式解析

核心避坑逻辑:MC协议的坑80%集中在“PLC配置”“地址编码”“字节序”,先解决这三点,通信就成功了一半;实战优先级:新手优先用开源库(Mitsubishi.MCProtocol),避免手动拼接帧格式的复杂坑;进阶再研究帧格式解析;排坑技巧:先Ping通→用调试助手验证→写C#代码,分层排查,不要混在一起找问题。掌握这些避坑技巧后,你可以轻松实现C#与三菱全系列PLC的稳定通信,满足工业场景中数据采集、设备控制等核心需求。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 2195

let与for循环

关于代码 for(let i = 0; i < btn.length; i ++){ console.log(i); btn[i].addEventListener('click',function(){ console.log(i); }) } 疑问1.为什么可以每次打印都打印循环中i的值而不是循环结束后i的值 理解:因为es6存在块作用域,而let声明变量是在当前作用域块的顶端,因为每一次循环都会生成一个作用域块,所

qq_40030159的博客 967

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

JavaScript高级程序设计学习 ① 完整的JavaScript包含什么?var、let、const的使用与异同?for循环中为什么最好使用let?Undefined、Null、NaN分别是什么?

一、完整的JavaScript包含什么?他们的含义又是什么?二、var、let、const的使用与异同?三、 for循环中为什么最好使用let而不是const、var四、Undefined、Null、NaN分别是什么?五、关系操作符,为什么会出现3 > 23 ?

zujiasheng的博客 797

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

js中Let和Var的区别

写在前面: 本文转载自:https://www.cnblogs.com/fly_dragon/p/8669057.html 作者:FlyDragon 出处:http://www.cnblogs.com/fly_dragon/ 关于作者:专注于微软平台项目架构、管理和企业解决方案。如有问题或建议,请多多赐教! 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,如有问题,可以通malun666@126.com 联系我,非常感谢。 正文: ES6 新增了let

wt1310445488的博客 2176

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

ES6 let 代替函数闭包解决问题

了解ES6的let属性与var的区别 let的介绍与var的区别 1.var没有块级作用域,而let有块级作用域 2.在js中只有function才有自己独立的作用域 如果没看懂: 举个例子: {var a=10} console.log(a); 1.在网页运行的时候a是可以直接打印的 2.如果将var换成let时 {let a=10} console.log(a); 1.控制台显示a未定义。 2.这说明let有自己独立的作用域。 3.既然有独立的作用域,那么let就能替代函数解决函数闭包问题。

好川的博客 4188

关于let的暂存性死区,方便自己查看

我用了两个月的时间才理解 let 方应杭 微信 xiedaimala02,公众号 XDML,暗号:知乎 679 人赞了该文章 当然不是说用完整的两个月时间来理解 let,而是零零碎碎地理解,同时我还要想着怎么写出一篇文章把这个事情说清楚。 在 let 刚出来的时候,我就「以为」我理解了 let。然鹅在过去的两个月里,我对 let 的理解发生了一波三折的变化。 我写这篇文章,是希望我...

A13330069275的博客 2971

什么叫死区时间_我用了两个月的时间才理解 let

当然不是说用完整的两个月时间来理解 let,而是零零碎碎地理解,同时我还要想着怎么写出一篇文章把这个事情说清楚。在 let 刚出来的时候,我就「以为」我理解了 let。然鹅在过去的两个月里,我对 let 的理解发生了一波三折的变化。我写这篇文章,是希望我的学习过程,能对你自学有帮助。初识 let跟很多人一样,我第一次了解 let 的特性是从 MDN 的文档:我得到的信息有这么几条:let 声明的变...

weixin_33453301的博客 595

【ES6 教程】第一章 新的ES6语法01—let:使用let关键字声明块范围的变量

英文 | https://www.javascripttutorial.net翻译 | 杨小爱前言ECMAScript 2015 或 ES2015 是对 JavaScript 编程语言的重...

web前端开发 428

rust(14)-if let,while let

PS F:\learn\rustlearn> rustc learn9.rs PS F:\learn\rustlearn> ./learn9.exe ok match有模式匹配作用,if let也有模式匹配作用 fn main() { let x1=10; if let 10=x1{ println!("ok"); }else{ println!("n...

The research on computer technolog 700

for循环中的var和let的区别

for (var i = 0; i < 3; i++) { setTimeout(function () { console.log(i) // 3s 后输出 3次3 }, 30 * 100) console.log(i) // 先输出 0 1 2 } 1、这道题涉及到了异步、作用域、闭包: settimeout是异步执行,...

mm 7124

浅谈js for循环中的let和var

在js中是没有块级作用域的,所以在后面的es6中有了let这个证明变量的方法来进行弥补。 大部分初学js的都会遇到这个问题 for (var i = 0; i < 2; i++) { setTimeout(() => { console.log(i); }) } 他会一直输出2,而不是0,1,这是js中的异步问题。 而我们使用let声明时 for(let i=0;i<5;i++){ setTimeout(function(){console.log(i)}) } 就会正常输出,而大家有没

HLJtheshy的博客 3694

let和var在for循环中的表现

声明变量的关键字var , let ,const。var是函数作用域,let,const是块级作用域。这里就来谈谈关于函数作用域和块级作用域,通过一个for循环的例子来解答两个作用域的差别,以及如何通过var声明来模拟let的特性。

黑黑黑客儿 6265

for循环中var和let的区别

今天在做题的时候,遇到了一个不太懂的问题,经过查阅资料,终于搞明白了这个问题,发出来当做个笔记。 首先是var: for (var i = 0; i < 5; i++) { setTimeout(function() { console.log(i); }) }; 输出结果: let方法: for (let i = 0; i < 5; i++) { ...

weixin_44703582的博客 6718

let在for循环中的灵活使用

我们都知道es6语法新增了两个关键字,let声明变量.const声明常量. 我们会发现,当我们利用for循环给一个元素集合添加事件时,事件驱动的函数里面是不能对应访问每个循环值的,只能访问最后一个,而当我们将for循环里面条件中声明变量的关键字该为let时,情况就发生了变化. 我们函数里面是能访问每次循环对应的值,这是为什么勒.此时我们就需要深究for循环的原理了. 经过我的多方查阅.最终我认为f...

qq_43390061的博客 2421
上一篇: 搭建vue框架(一):创建项目
下一篇: 搭建vue框架(二):项目配置
My_Java_Life
博客等级 码龄11年 39粉丝 61原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值