博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【前端工程师手册】JavaScript作用域拾遗
阅读量:6717 次
发布时间:2019-06-25

本文共 1110 字,大约阅读时间需要 3 分钟。

昨天总结了一些作用域的知识,但是发表完发现忘记了一些东西,今天拾个遗。

昨天说到了JavaScript中没有块级作用域,其实在es6中是有的。

es6中的块级作用域

先举个栗子:

var foo = true;if (foo) {    let bar = foo * 2;    bar = something( bar );     console.log(bar); } console.log( bar );  // ReferenceError

这个是let最直观的作用,在一对大括号中创建了块级作用域,bar会在大括号中的代码执行完毕后销毁。

再举个栗子:

for(var i = 1;i <= 5;i++) {    setTimeout(function() {        console.log(i)    }, i*1000)}// 每隔一秒打印一个6,共打印5次

如果说这段代码的初衷是间隔1秒打印出1、2、3、4、5的话,结果是令人大跌眼镜的,真正的结果是每隔1秒打印一次6,打印5次.

为什么会这样子?首先是因为闭包的原因,闭包后面再说,现在先理解为闭包是一个函数,一个能够访问并未在它自己内部定义的变量的函数。
OK,接下来说深层次原因。for循环完毕之后,i=6,且此时生成了5个匿名函数 function(){ console.log(i) },由于这5个匿名函数处在同一个词法作用域中,所以他们引用同一个i,所以当他们执行时,自然而然就会打出6。
如何解决?

for(let i = 1;i <= 5;i++) {    setTimeout(function() {        console.log(i)    }, i*1000)}// 间隔一秒分别打印出1、2、3、4、5

把var换成let声明就可以了。

《你不知道的JavaScript-上卷》中解释道:

for 循环头部的 let 不仅将 i 绑定到了 for 循环的块中,事实上它将其重新绑定到了循环的每一个迭代中,确保使用上一个循环迭代结束时的值重新进行赋值。

说白了就是再每次迭代内部,都会对 i 进行隐形的重新赋值,且使用的是上一个迭代结束时的值来对 i 进行重新赋值。

差不多就是这样的:

for(let i = 1;i <= 5;i++) {    let i = 上次迭代结束的i    setTimeout(function() {        console.log(i)    }, i*1000)}

所以5个匿名函数引用的并不是同一个i,自然就会顺利的间隔一秒分别打印出1、2、3、4、5了

转载地址:http://rmumo.baihongyu.com/

你可能感兴趣的文章
linux文件系统介绍
查看>>
find
查看>>
互联网MySQL开发规范
查看>>
android中的按钮以图片的方式显示_基础篇
查看>>
linux indent命令: 调整C原始代码文件的格式
查看>>
snmp之——2交换机MIB库ID和物理端口不对应
查看>>
Centos6.7下安装python连接mysql环境故障解决
查看>>
12.交换路由密码恢复
查看>>
sudo:sorry,you must have a tty to run sudo
查看>>
python os模块
查看>>
服务器操作系统之Solaris架构攻略
查看>>
java——演示封装的思想
查看>>
直接使用提交过来的类来更新字段EntityState.Modified并过滤null值的方法
查看>>
美团在Redis上踩过的一些坑-5.redis cluster遇到的一些问题
查看>>
浅谈JAVA的线程安全与性能之间的权衡
查看>>
python入门系列之一:Centos6下python2.7的安装
查看>>
31.软连接
查看>>
oracle 11g 手工热备-数据库
查看>>
跟我一起数据挖掘(17)——分布式缓存
查看>>
python paramiko 执行命令
查看>>