js中闭包的理解

js中闭包的理解对于闭包二字 我们常常听说 可能更加知道面试的时候 面试官必问知识点之一在 MDN 中 对闭包是这样定义的一个函数和对其周围状态 lexicalenvir 词法环境 的引用捆绑在一起 或者说函数被引用包围 这样的组合就是闭包 closure 也就是说 闭包让你可以在一个内层函数中访问到其外层函数的作用域 在 JavaScript 中 每当创建一个函数 闭包就会在函数创建的同时被创建出来 要想理解闭包 必然需要理解 js 的变量作用域 全局变量和局部变量我们都知道 在函数内部

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

在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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/227878.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月16日 下午8:19
下一篇 2026年3月16日 下午8:19


相关推荐

  • cv2 interpolate插值-align_corners

    cv2 interpolate插值-align_cornerstorchinterpo nn functional interpolate input size None scale factor None mode nearest align corners None recompute scale factor None input Tensor 输入数据 size intorTuple int orTuple int int orTuple int int int 输出数据的尺寸

    2026年3月18日
    2
  • 【sshd】sshd_config 中 PermitRootLogin 的forced-commands-only的限定密钥登陆、限定执行命令

    【sshd】sshd_config 中 PermitRootLogin 的forced-commands-only的限定密钥登陆、限定执行命令主讲:PermitRootLogin的可选项众所周知,sshd_config是sshd的配置文件,其中PermitRootLogin可以限定root用户通过ssh的登录方式,如禁止登陆、禁止密码登录、仅允许密钥登陆和开放登陆,以下是对可选项的概括:参数类别 是否允许ssh登陆 登录方式 交互shell yes 允许 没有限制 没有限制 without-password 允许 除密码以外 没有限制 forced-commands-on

    2022年6月1日
    32
  • JS定时器整理(执行一次setTimeout、重复执行setInterval)

    JS定时器整理(执行一次setTimeout、重复执行setInterval)js 定时器整理 执行一次 setTimeout 重复执行 setInterval 在 javascritp 中 有两个关于定时器的专用函数 分别为 1 倒计定时器 timename setTimeout function delaytime 2 循环定时器 timename setInterval function delaytime 第一个参数 function 是定时器触发时要执行的动作 可以是一个函数 也可以是几个函数 函数间用 隔开即可 比如要弹出两个警告窗口

    2026年3月19日
    3
  • 分位数回归模型学习笔记

    分位数回归模型学习笔记我读硕士老师给我的第一篇论文就是一个分位数回归的文章 当时觉得这个模型很简单 我很快就用 R 的示例文件写了一个例子 但是 在后面的研究中 我越来越觉得 这个模型没有我想的那么简单 而且有着非常丰富的内涵需要来挖掘 就找了好几本书来看 结果真的是越看越懵 越看越懵 但是懵了一段时间之后 又重新感觉自己明白点了 所以赶紧把这一点进行一个总结 省的再放一段时间 连仅有的这一点懂的东西都没有了 首先随机变量

    2026年3月16日
    2
  • cWinform自定义控件-目录

    cWinform自定义控件-目录官网 http hzhcontrols com 前提入行已经 7 8 年了 一直想做一套漂亮点的自定义控件 于是就有了本系列文章 GitHub https github com kwwwvagaa NetWinformCo 码云 https gitee com kwwwvagaa net winform custom control git 如果觉得写的还行

    2026年3月18日
    3
  • linux kworker cpu,Kworker,它是什么,为什么它占用这么多 CPU?[通俗易懂]

    linux kworker cpu,Kworker,它是什么,为什么它占用这么多 CPU?[通俗易懂]问题:有时候它几乎使用一半的CPU。答案1:运行”kworker”是内核工作线程的占位符进程,它执行内核的大部分实际处理,尤其存在中断,计时器,I/O的情况下。答案2:在进程列表中可以有几个:kworker/0:1是第一个CPU内核,kworker/1:1是第二个。kworker为什么要占用你的CPU?echol>/proc/sysrq-trigger执行此操作几次,然后在dmesg…

    2026年3月8日
    6

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号