JS闭包

JavaScript采用词法作用域,即在函数创建的时候保存函数的静态作用域链。闭包是指函数变量可以被隐藏于作用域之内。
JavaScript函数在创建时便会创建并保存函数的[[Scope]]属性,[[Scope]]保存所有父级变量对象。因此所有的函数都是闭包。

闭包实例

function outFun() {
  var v1 = "test";
  function innerFun() {
    alert(v1);
  }
  return innerFun;
}

var myFun = outFun();
myFun();//"test"

其中内部函数innerFun() 的[[Scope]]为:

innerFun.[[Scope]] = [
    outFunContext.AO:{v1 : "test"},
    globalContext.VO
]

因此在全局上下文中调用赋值给myFun的内部函数innerFun时,变量v1从innerFun.[[Scope]]中查找得到“test”。

同一父级函数的对象都引用一个[[Scope]]

在同一个父上下文中的多个函数有相同的[[Scope]]属性。在同一上下文中创建的函数,[[Scope]]属性中保存的是父类变量对象。因此同一个上下文中创建的多个函数的[[Scope]]属性相同。

var firstClosure;
var secondClosure;

function foo() {

  var x = 1;

  firstClosure = function () { return ++x; };
  secondClosure = function () { return --x; };

  x = 2; // 影响 AO["x"], 在2个闭包公有的[[Scope]]中

  alert(firstClosure()); // 3
}

foo();

alert(firstClosure()); // 4
alert(secondClosure()); // 3

循环中的闭包

最初遇到闭包和最常考验闭包的就是循环中创建闭包。

function fun() {
    var funcs = [];
    for(var i = 0; i < 10; i++) {
        funcs[i] = function() {
            return i;
        }
    }
    return funcs;
}

var f1 = fun();
f1[0]();//10
f1[5]();//10
f1[9]();//10

f1[0]-f1[9]这几个函数具有相同的[[Scope]],而[[Scope]]中的变量i随着循环递增,最终值为10,因此这几个函数的返回值都为10。

解决方法

(1)通过立即执行函数创建一个新的闭包

function fun() {
    var funcs = [];
    for(var i = 0; i < 10; i++) {
        funcs[i] = (function help(x){
            return function() {
                return x;
            }
        })(i);
    }
    return funcs;
}

var f1 = fun();
f1[0]();//0
f1[5]();//5
f1[9]();//9

函数help在传入参数i时立即执行,并且返回一个函数作为数组的值,函数help每次会创建新的包含x的变量对象,而x是由参数i传递来的。

因此函数的[[Scope]]情况如下:

f1[0].[[Scope]] = [
    helpContext.AO:{x:0},
    funContext.AO:{i:10},
    globalContext.VO
]
f1[5].[[Scope]] = [
    helpContext.AO:{x:5},
    funContext.AO:{i:10},
    globalContext.VO
]
f1[9].[[Scope]] = [
    helpContext.AO:{x:9},
    funContext.AO:{i:10},
    globalContext.VO
]

end

闭包可以实现函数的封装,获取函数内部变量。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值