谈谈JS中的闭包

浅谈闭包

如何产生闭包?

为了在函数外部访问函数内局部变量,就在父函数中定义一个子函数并让它访问了父函数的局部变量,再通过父函数返回该子函数就实现了调用局部变量的效果。

简单举例

function fun1() {
  let num = 1;
  return function fun2() {
    console.log(num++);
  }
}
const add = fun1();
add();

形成的条件

  • 函数嵌套(函数作参数,函数作返回值)
  • 内部函数访问外部函数的局部变量

可以把闭包理解成一个容器保存了这些值(调试时候看到的closure,里面有key: value保存闭包的值)

在案例中fun2这个函数访问了父函数的num,函数销毁前,num一直存在,我们每次调用fun2(),num值+1

闭包是什么?

这是我从网上找到的一些的解释。

闭包,不同于一般的函数,它允许一个函数在立即词法作用域外调用时,仍可访问非本地变量。 –维基百科

闭包就是能够读取其他函数内部变量的函数,闭包就是将函数内部和函数外部连接起来的一座桥梁。 –阮一峰

闭包就是对函数写作时的环境引用。
闭包是通过JS回收机制保留某段作用域的一种手段。

两点知识:

  • Javascript函数内部可以直接读取全局变量
  • 在JS中,变量查找遵循就近原则,如果同级没有该变量,则就一层一层向父级层查找。—“链式作用域”

闭包与GC垃圾回收

JavaScript的垃圾回收机制,简单来说就是:固定时间间隔,周期性的释放不在使用的变量所占内存。全局变量的生命周期直至浏览器卸载页面才会结束,局部变量只在函数的执行过程中存在。

垃圾回收有两个办法:标记清除和引用计数(具体不懂)。

简单点来说就是有没有被引用,没有被引用的就会被回收。

那么在闭包中,函数调用了父函数作用域的值,然后被return出去了,这个函数中使用的外部值也就没有被回收,直至函数销毁。

function fun1() {
  let num = 1;
  return function fun2() {
    console.log(num++);
  }
}
const add = fun1();
add();

结合上面的例子,父函数中的变量被子函数引用,子函数又被外部变量引用,可以说明闭包的产生和他们不被回收的原因。上面的列子中将全局的add=null就可以回收fun2了。

闭包的优缺点

闭包的优点:可以在内存中维持一个变量,由于闭包,定义一个父函数中的变量只有通过子函数访问到,无法通过其他途径访问修改,从而达到了保护变量安全的效果。

闭包的缺点:容易造成内存泄漏,所以不能滥用闭包。

闭包的场景

看网上还有一些场景:私有变量,安全,让变量始终保持在内存中,可以避免全局使用的变量都在window上等等,实际中的应用还不太清楚,网上资料也不多,还需磨练自己在实践中体会。

在之前写过的防抖和节流中,共同维护了一个定时器对象timer,其中产生了闭包,使得我们每次频繁操作的时候,先判断定时器状态,再执行业务逻辑,达到防抖和节流的效果。

题目

第一道

下面两段代码的运行结果是什么?------来自阮一峰的网络日志

var name = 'The Window';
var object = {
  name: 'My Object',

  getNameFunc: function () {
    return function () {
      console.log(this.name);
    };
  }
};
object.getNameFunc()(); // The window
var name = 'The Window';
var object = {
  name: 'My Object',

  getNameFunc: function () {
    var that = this;
    return function () {
      console.log(that.name);
    };
  }
};

object.getNameFunc()(); // My Object
// 使用了父级函数的that变量,形成闭包

第二道

以下代码的输出结果是什么?

function fun(n, o) {
  console.log(o);
  return {
    fun: function (m) {
      return fun(m, n);
    }
  };
}

console.log('-----a-----');
var a = fun(0);
a.fun(1);
a.fun(2);
a.fun(3);

console.log('-----b-----');
var b = fun(0).fun(1).fun(2).fun(3);

console.log('-----c-----');
var c = fun(0).fun(1);
c.fun(2);
c.fun(3);

运行结果
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值