图解JavaScript闭包面试题

article/2025/6/28 1:36:49

由于最近在学习关于闭包相关的知识,并且闭包这个知识点让我有点搞不太清楚其具体的定义,所以在网上也查阅了很多大佬的讲解和对闭包的一个定义。

 

最后感觉还是MDN上的说法感觉比较好理解一些,对闭包还是不太理解的道友可以尝试看一看。

MDN上是这样说的:闭包是函数和声明该函数的词法环境的组合

原地址:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures

 

在了解闭包的过程中遇到一个很多地方都出现的一个面试题,按照自己的想法想了下发现几乎没对...所以就花了些时间分析了一下,供自己以后忘记了可以回顾一下。

同时,如果这里依旧存在一些误区,希望各位大佬们在评论区帮忙指正,感激万分!

 

原题如下:

        function fun(n, o) {console.log(o);return {fun: function (m) {return fun(m, n);}};}var a = fun(0); // ?a.fun(1); // ?a.fun(2); // ?a.fun(3); // ?var b = fun(0).fun(1).fun(2).fun(3); // ?var c = fun(0).fun(1); // ?c.fun(2); // ?c.fun(3); // ?

有兴趣的道友们也可以试着先想一想答案,看下是否一致?

 

以下是解题思路:

1. 首先我对这个题画了下题目中两个fun函数中的一些信息 (可能不太完整,但是解题应该够用了)

2. 当执行 var a = fun(0); 时,内存中开辟了一块新的空间给这个新的对象,这个对象中定义了一个方法fun。并且在fun(0)执行时,在当前作用域下的变量信息如下:

 

因此,当该语句执行时,控制台打印的值为 undefined

 

3. 当执行 a.fun(1) 时,因为对象a中的fun方法在定义时所处的环境( [[scope]] )中存在一个变量n和变量o,

并且在这条语句执行的时候,变量n( 此时n的值为0 ) 被第三方 (除了函数fun和方法fun)引用了,也就是被外部的对象a引用了,因此产生了Closure(闭包)。

然后,这条语句的return执行的时候先执行 调用fun函数----> 把m的值传递给了fun函数中的n,把n传递给了fun函数中的o, 因此控制台中打印o的结果为0。

然而事情并没有结束,调用fun函数会返回一个新的对象,这个对象也会在内存中新开辟一个空间,而此时这个新对象中的方法fun被定义时所处环境中的变量n已经被赋值为m的值,也就是1了。

4. 当a.fun(2)执行的时候,发生了和上面一样的故事,并且内存中又被返回了一个新的对象且这个新对象中的方法fun被定义时所处环境中的变量n已经被赋值为m的值,也就是2

5. a.fun(3)执行同上,且这个新对象中的方法fun被定义时所处环境中的变量n已经被赋值为m的值,也就是3

故: a.fun(2) 和 a.fun(3) 在控制台中打印o的结果都为0,且不管你传的参数是多少,只要你没有改变a对象的值,那么输出的结果都是0,因为你传的参数都存在新的对象中了。

 

当时我这里存在一个疑问,每次执行n的值不是都被修改了吗,为什么结果都是0呢?

注意:因为你始终都是在调用a的方法,而你每次执行a的方法fun的时候又没有把新返回的对象重新赋值给a,所以a里面的fun方法被定义时所处环境中的变量n一直都是0

 

6. 当 var b = fun(0).fun(1).fun(2).fun(3); 执行的时候就和上面疑问中的情形是一样的了。

当 fun(0)执行的时候,同上面a.fun(0)一样,返回结果是undefined,且此时产生的新对象中,方法fun被定义时所处环境中的变量n为0

当 fun(1)执行的时候,相当于上面的a.fun(1)一样,都是输出0 (此时fun方法所处环境中的n为0),且返回一个新对象,新对象中的变量n为1

当fun(2)执行的时候,就不太一样了,因为是在前一条语句执行结果后面直接调用fun方法, 但此时的fun方法已经不再是fun(1)中的方法了,而是上面返回的新对象中的方法,也就是变量n为1的方法,所以,这里输出的结果为1,且返回一个新对象,新对象中的变量n为2

当fun(3)执行的时候,和fun(2)的情况一样,输出结果为新的对象中的n,也就是2

 

7. 到这里,var c = fun(0).fun(1); 应该就能够明白为什么这里输出对的结果是 undefined 和 0 了

因为道理和前面一样,第一个 fun(0) 给n传递了值,但是o没有,所以打印o的结果为undefined,第二个 fun(1) 将n的值传给了o, 所以打印的结果为0,且这里产生的对象被赋值给了变量c,此时方法fun被定义时的环境(也就是它的词法作用域)中的n是被重新赋值的1 (方法fun的形参m把被传过来的实参1,传递给了函数fun中的形参n)

故:c.fun(2) 和 c.fun(3)中c对象的fun方法被定义时的环境中的n都是1,所以输出的结果也是把n的值传递给fun函数中的o, 即输出1

 

此处是测试结果图:

以下是我博客园的地址:

https://home.cnblogs.com/u/ViavaCos/


http://chatgpt.dhexx.cn/article/ab6FrC5W.shtml

相关文章

10 个用图表解释JavaScript 闭包的面试题

英文 | https://betterprogramming.pub/10-javascript-closure-challenges-explained-with-diagrams-c964110805e7 翻译 | 杨小爱 闭包是函数式编程中的核心概念之一,是每个 JavaScript 开发人员必备的知识。在这里,我准备了 10 个关于闭包的面试挑战题&…

面试题-闭包

目录 什么是闭包? 闭包的产生 闭包中的变量 自动形成的闭包与内存占用 手动形成闭包 闭包的优点/特点 对闭包的小结: 闭包经典面试题一 闭包基础面试题二 闭包经典面试题三 闭包经典面试题四 真题解答 需要先掌握的知识 1.javascript中的作用域与…

关于闭包的7道面试题

每个JavaScript开发人员都必须知道闭包是什么。在JavaScript编码面试中,闭包经常被问及。 本文整理了一份关于JavaScript 闭包的 7 个有趣且难度递增的问题的清单。 拿一支铅笔和一张纸,试着在不看答案或运行代码的情况下回答问题。可能需要大约 30 分钟…

闭包中常见的面试题

1、声明函数 最普通最标准的声明函数方法,包括函数名及函数体。 function fn1(){} 2、创建匿名函数表达式 创建一个变量,这个变量的内容为一个函数 var fn1function (){} 注意采用这种方法创建的函数为匿名函数,即没有函数name var fn1…

闭包及闭包经典面试题

理解:什么是闭包? 1.密闭的容器,类似set/map容器,用来存储数据 2.闭包是一个对象,存放数据的格式:key:value 闭包形成的条件 1.函数嵌套 2.内部函数引用外部函数 function fun(){var count 1;functi…

css js写在一起 vue_问题记录(关于css、js、Vue、ES6)

一.css样式问题 1.一行省略以及多行省略问题 一行省略样式: width: 200px; // 必须是定宽 overflow: hidden; // 超出隐藏 text-overflow: ellipsis; // 隐藏部分用省略号代替 white-space: nowrap; // 文本内容不换行(默认在定宽的情况下换行) 多行省略样式: width: 200px; //…

React基础语法学习

React主要有如下3个特点: 作为UI(Just the UI)虚拟DOM(Virtual DOM):这是亮点 是React最重要的一个特性 放进内存 最小更新的视图,差异部分更新 diff算法数据流(Date Flow)单向数据流 学习Re…

class语法糖,尝尝嘛~~

语法糖(Syntactic sugar),也译为糖衣语法,是由英国计算机科学家彼得约翰兰达(Peter J. Landin)发明的一个术语,指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更…

一种小型后台管理系统通用开发框架中的Cache缓存设计 ES6学习笔记 探秘 flex 上下文中神奇的自动 margin...

一种小型后台管理系统通用开发框架中的Cache缓存设计 本篇博客记录一下我在实习的公司的后台管理系统开发框架中学习到的一种关于网站的缓存(Cache)的实现方法,我会在弄懂的基础上,将该方法在.net core上进行实现。因为公司开发都…

前端综合笔记-JavaScript-CSS-HTML-VUE-ES6-Typescript-axios浏览器与web安全 --从入门到入坟

文章为个人整合的笔记,并无商业用途 点进来之后你的噩梦就要来了,接下来是我从业以来整理的一些基础与难点(多数来源于阅读文章与实践中遇到的问题),如果你 是个小白: 推荐使用2~3周的时间来消化接下来的内容, 遇到不…

flex布局应用与踩坑

一、预告 本文不是一篇入门的文章所有请符合以下条件的战斗人员绕道: 1、初学前端,对前端的传统布局还不是很熟悉的人 2、后端人员对前端不打算深入学习的同学 二、开篇 flex布局原本是好几个月前就一直想学习的东西,当时flex布局还算是比较新…

前端面试+学习笔记(HTML+CSS+JavaScript+ES6+Vue+NodeJs)

前端面试学习笔记(HTMLCSSJavaScriptES6VueNodeJs) 一. HTML 1. 盒子模型 是什么:每个元素被表示为一个矩形的盒子,有四个部分组成:内容(content)、内边距(padding)、边…

ReactNative基础篇(1)语法、布局、组件通信

•1.1语法 •ES6语法:ECMAScript6.0(以下简称ES6)是JavaScript语言的下一代标准,已经在2015年6月正式发布了。它的目标,是使得JavaScript语言可以用来编写复杂的大型应用程序,成为企业级开发语言 •参考网…

HTML/CSS/JS 基本语法

前端 一、HTNL1、文件结构2、文本标签&#xff08;1&#xff09;块元素&#xff1a;div&#xff08;2&#xff09;行内元素&#xff1a;span&#xff08;3&#xff09;格式标签 3、图片、音频、视频&#xff08;1&#xff09;图片&#xff08;2&#xff09;音频< audio >…

flex 弹性布局

阮一峰的网络日志 首页 档案 上一篇&#xff1a;ES6 的功能侦测库 下一篇&#xff1a;Flex 布局教程&#xff1a;实 分类&#xff1a; 开发者手册 Flex 布局教程&#xff1a;语法篇 作者&#xff1a; 阮一峰 日期&#xff1a; 2015年7月10日 感谢 腾讯课堂NEXT学院 赞助本站&…

前端可能问到的面试题(ts,js,css,es6)

1.void,null,undefined&#xff0c;never,NaN void:无返回值&#xff0c;只能赋值undefined和null null:空值&#xff0c;表示不存在 undefined&#xff1a;未定义&#xff0c;声明了但没有赋值&#xff0c;对象没有赋值的属性&#xff0c;对象没有返回值 never&#xff1a;永…

利用es6和es5的继承方式写一个简单的弹窗

本片博文受到https://blog.csdn.net/zfzhuman123/article/details/90411793的启发,es6部分代码只改了一点点,逻辑也是遵照他的思想来的,而且es5继承的部分也是用了部分es6的语法 1.首先是index.html <!DOCTYPE html> <html lang"en"> <head><m…

Flex 布局教程:语法篇

阮一峰的网络日志 首页 档案 上一篇&#xff1a;ES6 的功能侦测库 下一篇&#xff1a;Flex 布局教程&#xff1a;实 分类&#xff1a; 开发者手册 Flex 布局教程&#xff1a;语法篇 作者&#xff1a; 阮一峰 日期&#xff1a; 2015年7月10日 网页布局&#xff08;layout&am…

Python全栈:ES6标准入门和Flex入门

文章目录 1 ES6标准入门2 开发环境搭建3 ES6与 JavaScript的关系4 ES6 变量与常量4.1 变量4.2 常量 5 ES6 解构赋值6 ES6 函数、箭头函数箭头函数理解this 7 JavaScript中的面向对象编程构造函数静态方法 8 ES6中的继承9 ES6中的模块化export的使用&#xff1a;import的使用在N…

ES6语法笔记

1.多行字符串 用反引号 表示&#xff1a; abc相当于 abc 2.字符串连接时使用变量 使用${变量名}直接引用字符串变量 var name 小明; var age 20; var message 你好, ${name}, 你今年${age}岁了!; alert(message); 3.字符串方法&#xff1a;不会改变原有字符串的内容&a…