前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >什么是闭包?「前端每日一题v22.11.8」

什么是闭包?「前端每日一题v22.11.8」

作者头像
FE情报局
发布2022-12-05 10:17:39
2400
发布2022-12-05 10:17:39
举报
文章被收录于专栏:FE情报局

什么是闭包?「前端每日一题v22.11.8」

问题

在javascript中,经常听见闭包,那什么是闭包,闭包有哪些用途?

概念

闭包就像它的字面意思一样,表示一个封闭的内存空间,就叫闭包。换言之,当每个函数被创建的时候,都有一个闭包。

在js中有全局变量和局部变量,在函数内部可以读取函数外部作用域,函数外部无法直接读取函数内部变量。因此一个函数可以形成一个闭包

代码

可以通过代码来具体展示一下什么是闭包

代码语言:javascript
复制
function init() {
  var name = "init"; // name 是一个被 init 创建的局部变量
  function alertName() { // alertName() 是内部函数,一个闭包
      alert(name); // 使用了父函数中声明的变量
  }
  alertName();
}
init(); // 弹出init

最终弹出init,但是init函数内部的name变量在函数外部是访问不到的,相信大家都理解。这个没有什么问题,我们再来一个例子

代码语言:javascript
复制
function init() {
  var name = "init";
  function alertName() {
      alert(name);
  }
  return alertName;
}
var fun = init();
fun() // 同样弹出init

这个同样弹出init,同上一个例子的区别就是init函数将内部的alertName函数导出。闭包是由函数以及声明该函数的「词法环境」组合而成的,这个环境包含了闭包「创建时」作用域内的「任何局部变量」,这个例子中fun是init内部函数alertName的引用,alertName实例维持了对于name的引用,所以fun调用时,name仍然可用

深入

借用「MDN」上的内容,闭包有什么用呢?

我们可以定义一个公共函数,令其可以「访问私有函数和变量」

代码语言:javascript
复制
var Counter = (function() {
  var num = 0;
  function change(val) {
    num += val;
  }
  return {
    incre: function() {
      change(1);
    },
    decre: function() {
      change(-1);
    },
    value: function() {
      return num;
    }
  }
})();

console.log(Counter.value()); /* logs 0 */
Counter.incre();
Counter.incre();
console.log(Counter.value()); /* logs 2 */
Counter.decre();
console.log(Counter.value()); /* logs 1 */

这里我们使用自执行函数创建了一个「词法环境」,然后再利用闭包暴露出来到Counter上

当然我们也可以不通过自执行函数创建多个计数器

代码语言:javascript
复制
var makeCounter = function() {
  var num = 0;
  function change(val) {
    num += val;
  }
  return {
    incre: function() {
      change(1);
    },
    decre: function() {
      change(-1);
    },
    value: function() {
      return num;
    }
  }
};

var Counter1 = makeCounter();
var Counter2 = makeCounter();
console.log(Counter1.value()); /* logs 0 */
Counter1.incre();
Counter1.incre();
console.log(Counter1.value()); /* logs 2 */
Counter1.decre();
console.log(Counter1.value()); /* logs 1 */
console.log(Counter2.value()); /* logs 0 */

Counter1和Counter2都是维护的自己的计数逻辑,都具有各自的独立性

「闭包的缺点」

闭包常见的一个问题就是for循环的问题,很多新手总是不理解以下代码输出什么

代码语言:javascript
复制
for (var i = 0; i < 4; i++) {
  setTimeout(function() {
    console.log(i);
  }, 1000);
}
// 结果是4个4,1s过后,词法环境的i都已经变成了4,解决方法是使用let或者闭包

闭包会使函数变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成性能问题,IE中可能导致内存泄露。

那解决方法是什么呢?「就是在退出函数之前,将不使用的局部变量删除」

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-11-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 FE情报局 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题
  • 概念
  • 代码
  • 深入
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档