【javascript】闭包

通过定时器从第一个元素开始往后,每隔一秒输出arr数组中的一个元素。

<script>
    var arr = ['one', 'two', 'three'];
    for(var i = 0; i < arr.length; i++) {
    setTimeout(function () {
        console.log(arr[i]);
    }, i * 1000);
    }
</script>

 但是运行过后,我们却会发现结果是每隔一秒输出一个“undefined”。

这是为什么呢?

setTimeout()函数与for循环在调用时会产生两个独立执行上下文环境,当setTimeout()函数内部的函数执行时,for循环已经执行结束,而for循环结束的条件是最后一次i++执行完毕,此时i的值为3,所以实际上setTimeout()函数每次执行时,都会输出arr[3]的值。而因为arr数组最大索引值为2,所以会间隔一秒输出“undefined”。

尝试如下代码,发现就可以了。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    <script>
        var arr = ['one', 'two', 'three'];
        for(var i = 0; i < arr.length; i++) {
        (function (time) {
            setTimeout(function () {
                console.log(arr[time]);
            }, time * 1000);
        })(i);
        }
     </script>
  </head>
  <body>
  </body>
  </html>

 对比两个代码的区别,有什么不同呢?

先谈谈什么是执行上下文环境

JavaScript每段代码的执行都会存在于一个执行上下文环境中,而任何一个执行上下文环境都会存在于整体的执行上下文环境中。根据栈先进后出的特点,全局环境产生的执行上下文环境会最先压入栈中,存在于栈底。当新的函数进行调用时,会产生的新的执行上下文环境,也会压入栈中。当函数调用完成后,这个上下文环境及其中的数据都会被销毁,并弹出栈,从而进入之前的执行上下文环境中。

第二个代码通过立即执行函数将索引i作为参数传入,在立即函数执行完成后,由于setTimeout()函数中有对arr变量的引用,其执行上下文环境不会被销毁,因此对应的i值都会存在内存中。所以每次执行setTimeout()函数时,i都会是数组对应的索引值0、1、2,从而间隔一秒输出“one”“two”“three”。

下面引出闭包的概念,即函数声明和函数表达式可以位于另一个函数的函数体内,在内部函数中可以访问外部函数声明的变量,当这个内部函数在包含它们的外部函数之外被调用时,就会形成闭包

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ོ栖落

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值