前端|在JS里有关于闭包的一些问题

欢迎点击「算法与编程之美」↑关注我们!

本文首发于微信公众号:"算法与编程之美",欢迎关注,及时了解更多此系列文章。

问题描述

首先我们先来欣赏一段代码

function test() { var arr = []; for(var i = 0; i < 10; i ++){ arr[i] = function (){ document.write(i + " "); } } return arr; } var Myarr = test(); for(var j = 0; j < 10; j ++){ Myarr[j](); }

我们首先定义了一个test函数,然后在这个函数里面定义了一个数组,再通过for循环给数组里面的每一位变成一个函数,作用就是打印当前i的值。再然后return这个数组,最后在test函数外部定义Myarr,就等于test函数的执行结果,最后再执行Myarr数组的每一位。按之前的理解是执行的结果应该是0-9十个数字。但是实际结果是十个10.

解决方案

我们先来分析,为什么会打印出10,按道理说应该是9。问题就在于第一个for循环,i从1执行到了9,此时又重新开始一次循环,此时9<10,所以i就变成10了。但是此时i不满足for循环了,所以不执行里面的函数了。我们可以用以下代码解释

for(var i = 0; i < 10 ; i ++){ document.write(i) } document.write(i)

我们再来看为什么会输出10个10呢。这个问题在于arr[i] = function(){document.write(i + " ")。代码在执行for循环的时候,前面i的值发生变化,但是在后面的这个function里面的i并不会发生变化,因为在循环的时候这个function只是一个赋值语句,它并不会去看里面的内容,只有在最后调用Myarr的时候在来看里面的内容,而此时i的值已经全部循环结束变成10了。那我们要是想要它输出0-9十个数字怎么办呢?

此时闭包已经形成了,闭包也分好的和不好的,出现这种情况就属于不好的。那么我们要怎么去避免呢。我们想要的就是for循环里面的function里的i能够跟随外面的i一起变化。此时我们可以采用立即执行函数,完整代码如下

<script> function test() { var arr = []; for(var i = 0; i < 10; i ++){ (function (j) { arr [j] = function () { document.write(j + " "); } }(i)); } return arr; } var Myarr = test(); for(var j = 0; j < 10; j ++){ Myarr[j](); } </script>

END

主 编 | 张祯悦

责 编 | 刘玉江

where2go 团队


微信号:算法与编程之美

温馨提示:点击页面右下角“写留言”发表评论,期待您的参与!期待您的转发!

本文分享自微信公众号 - 算法与编程之美(algo_coding)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-05-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏达达前端

Android开发工程师文集-layout_weight讲解

大家好,我是 Vic,今天给大家带来Android开发工程师文集-layout_weight讲解的概述,希望你们喜欢

9840
来自专栏达达前端

AndroidStudio制作底部导航栏以及用Fragment实现切换功能

大家好,我是 Vic,今天给大家带来AndroidStudio制作底部导航栏以及用Fragment实现切换功能的概述,希望你们喜欢

34430
来自专栏达达前端

【详细】Android入门到放弃篇-YES OR NO-》各种UI组件,布局管理器,单元Activity

人与人之间起初是陌生的,从了解到深知,到你与他(她)不分彼此时,你会丢下这个陪伴你的人吗?

9620
来自专栏达达前端

第57节:Java中流的操作以及编码解码

编码解码:编码时将信息从一种形式变成为另一种形式,成为编码.编码为coding,逆过程为解码.编码时用代码表示的,解码为Decoding,有了编码就有相关的编码...

8940
来自专栏达达前端

第46节:Java当中的常量池

在Java虚拟机jvm中,内存分布为:虚拟机堆,程序计数器,本地方法栈,虚拟机栈,方法区。

14150
来自专栏达达前端

第50节:Java当中的泛型

这就存在一个问题,如果集合存储元素时,而且存储对象有很多,而且对象类型不相同,就很容易导致隐患。

9960
来自专栏达达前端

第52节:String,权限修饰符,方法,集合

这个答案为1或者2,因为如果"dashu"这个字面值如果在常量池中已经出现过,那么就只创建一个对象,如果没有出现过就会创建两个对象,new的出现一定会有一个对象...

10230
来自专栏达达前端

Android开发工程师文集-1 小时学会各种Drawable

大家好,我是 Vic,今天给大家带来Android开发工程师文集-1 小时学会各种Drawable的概述,希望你们喜欢

10220
来自专栏达达前端

Android精通之AsyncTask与ListView讲解

了解AsyncTask异步,需要了解一下异步任务(多线程),什么是线程,可以这么说线程好比边吃饭边看电视,AsyncTask是为了方便后台线程中操作更新UI,本...

7430
来自专栏达达前端

Android开发工程师文集-相关控件的讲解,五大布局

大家好,我是 Vic,今天给大家带来Android开发工程师文集-相关控件的讲解,五大布局的概述,希望你们喜欢

10340

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励