闭包,立即执行函数解决闭包问题

一个简单的demo 讲述闭包
所谓闭包,简单来说就是函数内部的某个值被保存到函数外部。通常用return直接保存。

function test() {
  var arr = [];
  for(var i = 0; i < 10; i++){
      arr[i] = function () {
        console.log(i);
      }
  }
  return arr;
}
var myArr = test();
for(var j = 0; j < 10; j++){
  myArr[j]();
}

可以先行预测一下上述代码的的结果
这里写图片描述
发现输出十个10,但我本意想要它输出0~9
首先解释一下为何会出现十个10
如上述列子,在函数中定义了一个arr数组,让数组循环十次,在下标为0~9的数组内放入了 function () { console.log(i)}。然后将这个数组return出去。并赋值给了myArr.
然后再执行myArri
myArri里面是function () {console.log(i)}
所以输出i
这个时候电脑访问i。
i 到底是什么?
在function () console.log(i)}里面 没有i这个值,所以到function test(){}中寻找,里面有i,并且这个 i 因为循环十次,i从0累加到10,i == 10。所以这才输出了10。
这里要涉及到作用域,作用域链相关知识。
简单来说就是function () {console.log(i)} 这个函数继承了本身的值、父亲函数(就是包裹他的那个函数的值)以及全局的值。当他需要需要访问元素的时候,先访问本身有没有这个值,如果本身没有再访问父亲函数,最后访问全局。(当然这种讲述只是方便理解,若要详细了解里面的过程可以搜索一下相关文章。)
并且闭包出去的函数所包含的父亲元素的值是同一个,改变一个,其他里面也会改变。
这跟全局的值是一个道理。无论在哪里改变,这个值都会改变。

综上,最后输出的i,都是访问的一个值。

解决方法是用一个立即执行函数,一般JS在运行过程中,遇见函数定义就先存放起来,当函数执行时再执行。然而运行过程中一碰见立即执行函数就执行函数体。并且立即执行函数一旦执行完成就消失。
立即执行函数格式

(function(形参){}(实参))
或
(function(){})()
W3C推荐使用第一种

所以可以修改成下述代码

function test() {
  var arr = [];
  for(var i = 0; i < 10; i++){
    (function (j) {
      arr[j] = function () {
        console.log(j);
      }
    }(i))
  }
  return arr;
}
var myArr = test();
for(var j = 0; j < 10; j++){
  myArr[j]();
}

每一次存放的function () {console.log(i)}中有本身函数的值,立即执行函数的值,function test()的值,以及全局的值。
在这个函数中,每一次碰到立即执行函数就立即执行,执行完毕就消失。
所以第一次立即执行函数放入j=0,然后立即执行函数消失。这个属于立即执行函数的值就消失了,但是arr[0]中保存了这个j。
第二次立即执行函数会重新生成一个文档,放入一个全新的j=1.同理这个j会被保存到相应的arr[1]中。
也就是说每一个arr[i]中关于立即执行函数所给的值不是同一值。
原因是立即执行函数执行完毕就消失了。再次运行,就是一个新的函数。

所以myArr[i]里面的j值是不一样的。

这里写图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值