Kalec的网络日志

未来连结

HOME 首页 JavaScript的闭包(上)

JavaScript的闭包(上)

基础总结
2018-03-06 13:31:00

闭包和原型链是JavaScript这门语言的核心,到目前为止,我对闭包也只是一个肤浅的认识。就先试着写一点吧…

起初我只知道闭包大概就两个作用,一个就是模仿块级作用域,另外一个就是js实现变量的私有。然后对其中的细节全然不知,直到我看到了这样一个问题

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

惯性思维脱口而出,每秒依次输出1,2,3,4,5…

其实,并不,它每秒依次输出6…

为什么会出现这种情况呢?大概有两个原因

1.js的执行机制导致,js会自动把耗时的回调放到同步队列后面执行(改天咱们再来谈谈js的执行机制)

2.众所周知,js在es6出来前是没有块级作用域的,使得循环的5个函数共享同一个作用域

好,咱们整理一下,就是定时器回调函数被放到了循环之后执行,循环终止i为6。因为作用域共享,循环得到的结果依次被覆盖,最后就当然全部是6啦。

怎么解决这个问题呢?

当然就是靠闭包!

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

因为js的作用域为函数级作用域,那就先创建一个自执行函数,执行循环的时候依次给自执行函数内传入i,用一个变量接收,这个变量作用范围仅在这个函数内部,循环创建的5个函数互不影响,因而在循环执行完毕后到达对应时间点输出结果就得到意想的结果!是不是很棒!

捋一捋思路,其实这也便是其他语言块级作用域的优点,js在没有es6前块级作用域就是如上那样用创建函数来模拟的,当有了es6之后,整个世界似乎变得更加有趣了

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

换成let声明一切又变得那样亲切…

留言

  • 暂时没有留言,来留下你的留言吧!

评论

看不清?换一个