对闭包的简单理解?

优点简单的小练习与大家分享》

function fun0(){
    var a=1;
    console.log(a);
}
function fun1(){
    console.log(a);
}
fun0(); //1
fun1(); //报错 a is not defined

这段代码,我相信大家应该知道最后为什么结果会是 1 和 报错 的,在函数内声明的变量只在函数体内定义,它们是局部变量,作用域是局部的,所以 函数 fun1 调用后,找不到a,就报错了,JavaScript使用闭包就会解决这种问题,所以我们只要改改上面函数 fun1的位置,它就不会报错了。

function fun0(){
    var a=1;
    console.log(a);
    
// 把fun1放在fun0中,就不报错了
     function fun1(){
        console.log(a);
    }
    fun1();   //1
}
fun0();   //1

代码改成这样,只是把fun1 放在 fun0 中就不报错了,函数调用后都输出1

有这样一道题

for (var i = 1; i <= 5; i++) {

  setTimeout( function timer() {

   console.log(i);

  }, 1000 );

}

上面的代码会输出什么?怎么改动上述代码,使其依次输出1、2、3、4、5
答案是 程序会输出5个6 !!!重要的事情说三遍 ! ! !

setTimeout()相关知识:

在我们学习setTimeout的时候就知道,setTimeout有两个参数,第一个参数是回调函数,第二个参数是毫秒数,表示要执行回调函数所要延迟的时间。 因为setTimeout()函数要等执行完函数调用栈中的代码,然后立即调用定时器。这是因为,我们的定时器都被放在了一个被称为队列的数据结构中,等待上下文的可执行代码运行完毕后,才开始运行定时器,也就是定时器才刚开始计时。所以在定时器的方法执行的时候,变量i已经变成了6,所以输出的全部是6。


那么怎么样才能输出1、2、3、4、5呢 ?

因为5个定时器所打印出来的是同一个i变量,所以想要实现输出不同的数字,就需要把每个定时器所访问的变量独立起来,这就用到了JavaScript的闭包。闭包用途很多,可以很好地区分开各个作用域,避免变量的混淆,但是滥用闭包也会导致性能问题。那么通过下面的修改就可以了;

for (var i = 1; i <= 5; i++) {

    (function(i){

        setTimeout( function timer() {

              console.log(i);

          },  1000 );

    })(i);

}

块级作用域–关键字let

使用闭包可以得到正确的结果,原因就是改变了i的作用域,那如果我们把循环中的每个setTimeout都独立成一个作用域是不是也能实现同样的结果呢?我们都知道,在JavaScript中,每个函数是一个独立的作用域,但是“{}”是不能形成独立作用域的。

在ES6中提出了一个新的关键字let,就可以声明一个仅对当前“{}”内部有作用的变量。输出的结果是一样。

for (let i = 1; i <= 5; i++) {

  setTimeout( function timer() {

      console.log(i);

  }, 1000 );

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值