闭包的经典例子讲解

声明

文章中的例子不是我举的,是我复制别人的例子,但是讲解思路是我自己整理的。
为的就是给大家分享另外一种思考的方式,比如你曾经看见过这个例子但是看讲解没看明白,或者是闭包的知识比较模糊,那么我就来用我的思路帮大家再讲一遍。
如果你连作用域的知识都不知道,那么我推荐你先去看看别的博主的文章再回来看我的讲解。

小知识

在开始之前,我先说一下词法作用域
敲黑板啦!重点重点!
词法作用域简单来说就是,函数声明时的作用域。相反的还有动态作用域,也就是函数调用时的作用域。我今天我们只针对词法作用域进行讲解。

函数作用域中调用某个变量,如果该属性不存在于该作用域,那么就会冒泡到父级作用域去找,没找到继续一层一层冒泡直到全局作用域(window),还没找到则会报undefined。

例子

如果你看了我的上篇文章,一定对这个例子很熟悉

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

最终打印结果是66666,如果我想打印12345,上篇文章讲述了怎么通过ES6的let来解决该问题


但是这次,我们通过闭包的方式来讲解。下面这个例子也是我拷贝的
for (var i=1; i<=5; i++) {
    (function() {
        setTimeout( function timer() {
            console.log( i );
        }, i*1000 );
    })();
}

这样能够打印12345吗?不能,仍然是66666,为什么?
我明明也拿一个函数作用域——function将代码包裹了,为什么还是没用?
首先我们来看看,这function是不是一个闭包?
function是一个函数作用域,而且函数作用域中嵌套另外一个函数作用域timer,
看起来它好像是一个闭包是吧?
但是我们分析一下闭包的两个作用:
(1)在函数外部访问函数内部变量成为可能;
(2)函数内部变量离开其作用域后始终保持在内存中而不被销毁。

这里重复强调内部变量,内部变量,但是我们的 “闭包” function有函数内部变量吗?

是的,没有,那么当timer去闭包里找寻内部属性i,没找到,于是只能去到全局(window)找变量i,找到的i=6;


好,我们再看下一个例子,将 i 作为形参传入"闭包" function

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

最终输出结果成功输出为12345,除此之外,我要说这是一个真实的闭包,为什么?

因为funtion不仅有函数作用域,还有内部属性(形参j)。每次循环声明一个闭包function,而里面的内部函数timer冒泡访问外层作用域的数据就近访问到了function的内部属性(形参i),因此不会去全局作用域(window)访问i,这样就将timer的外部冒泡找寻 i 的行为阻拦在了闭包function的作用域。

太抽象听不懂?说白点就是,我function有值了!你别再去找外面的男人(i)了
而上面那个例子则是,抱歉我function一无所有,我能拥有你但我留不住你,我不是男人(闭包)
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值