51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

JS 闭包特性(Closure)

文章已同步至掘金:https://juejin.cn/post/6844903930082623496
欢迎访问😃,有任何问题都可留言评论哦~

什么是闭包?

闭包就是能够读取其他函数内部变量的函数。

例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成"定义在一个函数内部的函数"。
在本质上,闭包是将函数内部和函数外部连接起来的桥梁。

代码演示:

function里嵌套function时,内部的function可以访问外部function里的变量

function fn(x) {
  var tmp = 3;
  function bar(y) {
    alert(x + y + (++tmp));
  }
  bar(2);
}
fn(1)

不管执行多少次,都会alert 7,因为bar能访问fn的参数x,也能访问fn的变量tmp

但是,这并 不是 不是 不是 闭包

当你return的是内部function时,才是闭包

内部functionclose-over外部function的变量直到内部function结束。

function fn(x) {
  var tmp = 3;
  return function (y) {
    alert(x + y + (++tmp));
  }
}
var bar = fn(1); // bar 现在是一个闭包
bar(2);

上面的脚本最终也会输出alert 7,因为虽然bar不直接处于fn的内部作用域,但bar还是能访问xtmp

但是,由于tmp仍存在与bar闭包的内部,所以它还是会自加1,而且你每次调用bar时它都会自加1。

其实,我们其实可以建立不止一个闭包方法,比如return它们的数组,也可以把它们设置为全局变量。它们全都指向相同的x和相同的tmp,而不是各自有一份副本。

一个需要关注的点:

JS里处理object时是用到引用传递的,那么,你调用fn时传递一个objectfn函数return的闭包也会引用最初那个object

function fn(x) {
  var tmp = 3;
  return function (y) {
    alert(x + y + tmp);
    x.memb = x.memb ? x.memb + 1 : 1;
    alert(x.memb);
  }
}
var tar = new Number(1);
var bar = fn(tar); // bar 现在是一个引用了tar的闭包
bar(2);

不出我们意料,每次运行bar(2)x.memb都会自加1。但需要注意的是x每次都指向同一个object变量tar

这样内存泄漏有关。

有一个不用return关键字的闭包例子:

function closureExample(obj, text, timedelay) { 
    setTimeout(function() { 
        document.getElementById(objID).innerHTML = text; 
        }, timedelay); 
} 
closureExample('myDiv', 'Closure is created', 500); 

总结:

JS里的function能访问它们的:

  • 参数
  • 局部变量或函数
  • 外部变量

如果在一个函数中,又嵌套了一个函数,并且里面这个函数引用外面的函数的变量,那么就是闭包。

闭包的特点:

  • 闭包可以产生内存泄露
  • 闭包可以延长变量的生命周期

~~ {#}

赞(2)
未经允许不得转载:工具盒子 » JS 闭包特性(Closure)