一个经典的块级作用域例子拆解

例子

例一:

for (var i=1; i<=5; i++) {
    setTimeout( function timer() {
        console.log( i );
     }, i*1000 );
}

运行结果是66666

例二:

for (let i=1; i<=5; i++) {
    setTimeout( function timer() {
        console.log( i );
     }, i*1000 );
}

运行结果是12345

我在网上找到很多关于这个例子的讲解,第一个例子很容易(就是setTimeout是异步执行的,当延时显示时,循环体早就结束了,i=6所以输出的全是6),至于第二个例子我也看了很多讲解就是没弄懂。但是恕我愚笨,他们有的讲的太抽象,有的就根本没讲到真正的点上。
因此我打算自己通过拆解循环的方法来帮大家分析一下。

首先,
拆解例一

var i=1;
setTimeout( function timer() {
        console.log( i );
     }, i*1000 );
i++;
setTimeout( function timer() {
        console.log( i );
     }, i*1000 );
i++;

setTimeout( function timer() {
        console.log( i );
     }, i*1000 );
i++;

setTimeout( function timer() {
        console.log( i );
     }, i*1000 );
i++;

setTimeout( function timer() {
        console.log( i );
     }, i*1000 );
i++;

不难看出function timer()定义时,内部(括号里面)不包含i这个变量,那么延时结束后它就会到外层去找(大括号为界限),而外层的i此时已经为6。

下面拆解例二:

let j = 1;
{		//!!!!!!!!!看!这个大括号就是循环自动生成的块级作用域
let i =j		//可以访问父级作用域
setTimeout( function timer() {
        console.log( i );
     }, i*1000 );
}
j++;

{
let i =j
setTimeout( function timer() {
        console.log( i );
     }, i*1000 );
}
j++;

{
let i =j
setTimeout( function timer() {
        console.log( i );
     }, i*1000 );
}
j++;

{
let i =j
setTimeout( function timer() {
        console.log( i );
     }, i*1000 );
}
j++;

{
let i =j
setTimeout( function timer() {
        console.log( i );
     }, i*1000 );
}
j++;

这里在循环每次执行都会生成一个块级作用域,并将循环参数传给该块级作用域作为参数。
这里之所以用 j 来代原本替循环体内的 i 是因为let不可以重复定义同名变量。

大家可以复制代码到浏览器控制台运行一下来验证。
如果这还看不懂,那么你得好好回去补一补作用域的知识了,可以的话把闭包也补补

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值