js中闭包的理解

本文详细介绍了JavaScript中的闭包概念,包括MDN的定义、变量作用域、闭包的创建及作用。闭包允许在函数外部访问内部变量,提供了一种保护和保存变量的方法。它在内存管理上可能会导致消耗,需要注意避免滥用。通过实例解析了闭包如何影响`this`的指向,并提出了解决方案。闭包在保护变量、持久化数据等方面有重要作用,但也需注意内存占用问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对于闭包二字, 我们常常听说, 可能更加知道面试的时候, 面试官必问知识点之一

MDN 中, 对闭包是这样定义的

一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包(closure)。也就是说,闭包让你可以在一个内层函数中访问到其外层函数的作用域。在 JavaScript 中,每当创建一个函数,闭包就会在函数创建的同时被创建出来。

要想理解闭包, 必然需要理解js的变量作用域: 全局变量和局部变量

我们都知道, 在函数内部可以读取全局变量

  var a = 1;
    function fn () {
     console.log(a) // 1
    }
   fn()

但是如果我们把a变量定义在函数内部 , 需要在函数外部使用. 则失败

在这里插入图片描述
那么我们怎样才可以使用函数内部的局部变量, 这就引进了闭包

 function fn() {
    var a = 1
      function fn2() {
        console.log(a)
      }
      return fn2
    }

  var f = fn()
  f()

在本例中 f是执行fn执行时创建的fn2函数

在上述代码中 函数fn2是被包含在fn内部的, 这时fn内部的所有局部变量对fn2是可以访问的. 但是反过来不可以, fn2内部的局部变量对fn是不可见的, 这就是js的链式作用域结构, 子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。

所以fn2函数就是闭包 , 第一个函数fn执行以后, f被赋值了 f = function fn2() { console.log(a)}, 每次调用fn函数的时候, 都是返回的这个函数, 因为这个函数在第一个函数内部, 所以即使第一个函数执行完, 第二个函数依然能访问到a(作用域链)

根据阮一峰的理解闭包就是能够读取其他函数内部变量的函数

而且在JavaScript高级程序设计中也有提到`闭包是指有权访问另一个函数作用域中的变量的函数

那么闭包的作用很显然就是

1. 可以在函数外部访问到函数内部的局部变量: 函数执行, 形成私有的执行上下文, 使内部私有变量不受外界干扰,起到保护(避免命名冲突)和保存(解决循环绑定引发的索引问题)作用
2. 让这些变量始终保存在内存中, 不会随着函数的结束而自动销毁: 是变量不会被垃圾回收机制回收

使用闭包的注意点

1. 产生内存消耗问题: 由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
2.由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

思考题

以下两个例子是阮一峰老师给出的思考题

 var name = "The Window";

  var object = {
    name : "My Object",

    getNameFunc : function(){
      return function(){
        return this.name;
      };

    }

  };

  alert(object.getNameFunc()())

结果是The Window why?
我们可以把最后一句拆分一下

   var fn1 = object.getNameFunc();
      console.log(fn1());

由于执行fn1()函数时是 window.fn1(), 所以这里的this指向是window, 所以window.name就等于The window

 var name = "The Window";

  var object = {
    name : "My Object",

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

    }

  };

  alert(object.getNameFunc()());

结果是My Objec 我们用同样的方式

   var fn1 = object.getNameFunc();
      console.log(fn1());

对于object.getNameFunc()我们可以知道, 它的this指向的是它的调用者object, 在执行fn1之前, 声明了一个that变量来保存object, 所以执行fn1()时, 此时的that就是object, that.name当然就是
My Object

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值