1,块级作用域。这里想说的是,在一个块{}中,使用const或let 声明一个变量,这个变量将统治整个块(consumes the entire scope),无论你在块的什么地方声明这个变量。就算,你是在块的底部声明了一个变量, 但是这个变量的作用域,实际上从块的起始部位开始算起,一直到块的结束,存在着某种意义上的变量提升。

if(true) {
// data 变量的作用域从这里开始
console.log();
console.log() let data = new Date();
// data 变量的作用域在这里开始
}

  变量存在提升,这也就意味着,我们有可能无意地使用了后面声明的变量,尤其是当变量作用域外部有一个和它重名的变量时

let data = ;

if(true) {
console.log(data);
console.log();
console.log() let data = new Date();
}

  运行这段代码,报错了。刚开始的时候,以为第一行的data 读取的是外部的变量data(1), 因为内部的data 变量还没有声明。其实不是,只要在块中声明了变量,这个变量将统治整个块。第一行的console.log 读取的是块中最后一行声明的变量。尽管能读取变量,但不能使用这个变量。在一个作用域中,在let 或const 变量声明之前,使用这个变量,将抛出引用错误。能够读取,但不能使用变量的区域就是暂存死区。在一个作用域中声明一个变量,暂存死区,指的就是作用域开始位置,到变量声明位置结束,引用暂存死区中的变量就会抛出引用错误。

  2,const 指的是不能重新赋值, 而不是值不能改变。Constants can not be reassigned. Constants are not immutable.

  一定要区分值和变量。5,false,  {name: 'sam'} 就是值。变量,是需要声明的,let a;  它其实是在内存中开辟了一个空间,用于保存东西。变量和值是相互独立的。可以声明一个变量,不给它值,那这个变量就什么都不能做。也可以只写一个值,不赋值给任何变量,但这个值只能用一次。当把一个值赋给一个变量的时候,它们有了关系,产生了绑定,变量名和值绑定到一起了,这叫assigin. const 指的就是这一块内容。值能不能改变,只关系值本身,它不关系和变量的关系。数字5,它就不能再改变了, 但对象就可以改变。

  3, let 和 const 在for 循环中使用

  let 声明的变量只在for 的循环体中有效,循环结束后 变量就消失了, 同时const 也可以在for 循环中声明变量,但是不能用于 常规的for 循环中。所谓的常规for 循环就是for(let i =0; i < 10; i++) 的格式。

  在使用for 循环的时候,每一次的迭代都会重新声明一个变量。像for(let i = 0; i < 10; i++); 这样使用时,i 变量声明了10次,只不过每一次迭代给i 赋值不一样而已,并且变量只在循环体中使用。 我们可以这样理解: 第一次迭代的使用,声明了一个变量i, 赋值为0, 0 < 10, 然后执行循环体,执行完之后i++ 变成了1. 这一次迭代就结束了,这个i 的使命就完成了。然后进行第二次迭代,这时重新声明一个变量i, 不过这次给他赋值为1,1 < 10 继续执行循环体,然后加1. 这次迭代又结束了,这个i 也完成了使命,消失了。第三次迭代进行同样的操作,声明一个全新的变量i,执行循环体之类的,直达整个循环结束。

  对于for 循环来说,每一次的迭代都是重新声明一个全新的变量i,只是赋的值是上一次迭代完成时的值,这样的话,循环体内获取到的i, 每次也都是全新的变量i,而不是像使用 var 声明时得到的是全局变量,并且,每一次迭代完成后,i 变量就消失了。

let funs = [];

// 使用var 声明循环变量i
for (var i = 0; i < 10; i++) {
funs.push(function(){
console.log(i);
})
}
// funs.forEach(item => item()); // 输出10个10 // 改为使用let 声明循环变量
let funss = []; for (let i = 0; i < 10; i++) {
funss.push(function(){
console.log(i);
})
} funss.forEach(item => item()); // 输出0, 1, 2, 3, 4, 5, 6, 7, 8, 9

  除了常规的for 循环之外,还有for-in 和for-of 操作, 原理都是一样的,他们每一次的迭代都是重新声明一个全新的迭代对象,而不是给原来声明的迭代对象赋新值, 循环体内获取到的都是当前迭代对象的值。

let funcs = [];
let arr = [1, 2, 3];
// for-in 循环, 数组是不建议使用for-in ,这里只是简单的演示
for (let key in arr) {
funcs.push(function() {
console.log(key);
});
}
funcs.forEach(function(func) {
func(); // 输出0, 1, 2
}); // 使用for-of
funcs = [];
for (let key of arr) {
funcs.push(function() {
console.log(key);
});
} funcs.forEach(function(func) {
func(); // 输出1, 2,3
});

  现在看一下const, const 也可以使用在for循环中。最简单的就是把上面的三个for 循环中的let 都转换为const.  for (const i = 0; i < 10; i++) {};   for (const key of arr) {} , for (const key in arr) {} . 这时你会发现第一种常规for 循环报错了。看一下第一次迭代就知道了。声明了一个 变量i, 赋值为0。 但这里使用const, 也就意味着i 在声明之后,就不能再改变了。好了,0 < 10, 执行循环体,然后  加1,报错了,i 不能变化了。一次迭代都没有走完,就报错了,说明,在使用常规for 循环时, const  不能用来声明变量。

  再来看一下,for-of, for-in, 没有问题,因为每一次的迭代都会声明一个全新的key, 所有的赋值都是给一个新的变量赋值,而没有改变原来的值。那使用let 和 const 有什么区别吗? 当然有了,还是在于const  声明的变量不能重新赋值了,所以如果for-in 或for- of 中使用const 声明了变量( 如key), 循环体中,就不能给key 赋新值了,如果使用let ,那就无所谓了,想干什么就干什么。只不过for-in 或for-of 中,我们很少改变key 值,所以他们在实际使用时就没有什么区别了。

let 和 const 在for 循环中的使用的更多相关文章

  1. 三. var let const的理解 以及 立即执行函数中的使用 以及 for循环中的例子

    一. 立即执行函数 windows中有个name属性,name='' '' var 如果我们用var name 去声明,那就会改变windows中name的值(因为我们不是在函数作用域中声明的,所以会 ...

  2. js循环中使用async/await踩过的坑

    最近写koa的时候遇见需要在循环中使用async/await的情况,当然第一反应就是直接上forEach,然后就直接翻车了... 直接上代码: function handleSql(val) { re ...

  3. 简单的node爬虫练手,循环中的异步转同步

    简单的node爬虫练手,循环中的异步转同步 转载:https://blog.csdn.net/qq_24504525/article/details/77856989 看到网上一些基于node做的爬虫 ...

  4. 「译」forEach循环中你不知道的3件事

    前言 本文925字,阅读大约需要7分钟. 总括: forEach循环中你不知道的3件事. 原文地址:3 things you didn't know about the forEach loop in ...

  5. java 在循环中删除数组元素

    在写代码中经常会遇到需要在数组循环中删除数组元素的情况,但删除会导致数组长度变化. package com.fortunedr.thirdReport; import java.util.ArrayL ...

  6. Java 循环中标签的作用

    continue和break可以改变循环的执行流程,但在多重循环中,这两条语句无法直接从内层循环跳转到外层循环.在C语言中,可以通过goto语句实现多重循环的跳转,但在非循环结构中使用goto语句会使 ...

  7. For each循环中使用remove方法。

    List<String> list =new ArrayList<String>(); list.add("boss"); list.add("g ...

  8. C#Random函数在循环中每次获取一样的值

    首先需要了解一点Random函数的随机生成是和当前时间有关系,如果在短时间生成随机数,就会导致随机数生成出来是相同的. 不过我们可以在每次随机时指定一个Seed种子值,这样在循环里就可以每次获取不一样 ...

  9. js for 循环中的 变量问题。

    今日处理项目中的一个循环,本来就是一个小小的for循环,后来发现该段程序出现了问题,仔细检查代码没有发现其中的错误.无奈只好叫来了老大帮忙.通过在模版中断点调试(该方式只能自己写debugger断点) ...

随机推荐

  1. Python编程从入门到实践笔记——用户输入和while循环

    Python编程从入门到实践笔记——用户输入和while循环 #coding=utf-8 #函数input()让程序暂停运行,等待用户输入一些文本.得到用户的输入以后将其存储在一个变量中,方便后续使用 ...

  2. Asp.Net MVC Unobtrusive Ajax

    1.   Unobtrusive JavaScript介绍 说到Unobtrusive Ajax,就要谈谈UnobtrusiveJavaScript了,所谓Unobtrusive JavaScript ...

  3. base64字符串转文件,以及ngImgCrop裁剪图片并上传保存到服务器示例

    base64字符串是包含文件格式的文件字符串,例如:data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAgAElE ...

  4. 简述ADO中如何使用参数化的命令对象以及增删改查,存储过程的操作

    连接数据库代码: private SqlConnection con = null; public void OpenConnection(string connectionString) { con ...

  5. WPF 自定义 ImageButton

    控件源码: public class ImageButton : Button    {        public ImageButton() {        } public string No ...

  6. IE中iframe标签显示在DIV之上的问题解决方案

    在做网页时前端时,使用IE打开时会出现标题栏DIV被遮挡PDF遮挡, 后在stackoverflow中查到是IE浏览器的问题:链接https://stackoverflow.com/questions ...

  7. Python数据处理与计算——概述

    Python是一种面向对象的,动态的程序设计语言,具有非常简洁而清晰的语法,适合于完成各种高层任务.它既可以用来快速开发程序脚本,也可以用来开发大规模的软件. 随着NumPy.SciPy.Matplo ...

  8. Python 标准类库 - 因特网协议与支持之socketserver

    标准类库 - 因特网协议与支持之socketserver by:授客 QQ:1033553122 socketserver 模块,简化网络服务编写任务. 创建服务的步骤 1  通过子类化BaseReq ...

  9. ASP.NET Zero--WEB.HOST应用程序

    WEB.HOST应用程序 AspNet Zero解决方案包含一个额外的项目Web.Host,它将所有应用程序功能公开为API.因此,您可以从任何设备使用API​​.实际上,Web.Mvc项目也是这样做 ...

  10. pipe size设置

    我所用的软件架构,使用pipe来实现线程之间的大量数据的传输.在实际操作中,pipe中传输的是数据的指针,而不是数据本身.  但是在调试过程中,我发现,如果我尝试往pipe里面write10000个指 ...