闭包相关

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

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

  1. 当执行 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了。

在这里插入图片描述

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

  2. 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

  1. 当 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

  1. 到这里,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

此处是测试结果图:

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值