阿里经典闭包面试题

阿里经典闭包面试题参考视频 https www bilibili com video BV1xf4y1R7AH 一 小试牛刀先来回顾一下 JS 的两种数据类型 基本数据类型和引用数据类型 基本数据类型 number null boolean string undefined symbol es6 引用数据类型 object array function 两道小题感受一下 1 基本数据类型题 leta 22 letb a b 33 console log a 打印 22

参考视频:https://www.bilibili.com/video/BV1xf4y1R7AH

一、小试牛刀

先来回顾一下JS的两种数据类型:基本数据类型和引用数据类型。

  • 基本数据类型:number 、null、boolean、string、undefined、symbol(es6)
  • 引用数据类型:object(array)、function

两道小题感受一下

(1)基本数据类型

题:

let a = 22; let b = a; b = 33; console.log(a); //打印22 

解析:

先创建基本类型的值22(存在栈内存当中),然后再赋值给a(将a和22关联在一起)。

=的作用:先创建值,接着创建变量,最后将变量和值关联。

image-20210917092601510

(2)引用数据类型

题:

let a = { 
   n:12}; let b = a; b['n'] = 13; //b通过地址找到对应的堆内存,把这个地址的值修改 console.log(a.n); 

解析:

先创建一个对象,是引用类型的值(不能存在栈里面,要单独开辟一个堆内存,使用地址去寻找它),把这个地址放到栈里边,供变量来调用。

image-20210917093143023

总结:基本数据类型是存到栈里边直接进行操作,而引用数据类型则是存在堆里面,并提供一个地址供栈内的变量去寻找。

二、大餐

闭包:当前函数执行,形成一个私有的上下文,函数执行完,当前私有上下文中的某些内容,被上下文以外的内容所占用,那么当前上下文就不能被释放 ==> 闭包。

闭包的作用:保护和保存。

let a = 0,b = 0; function A(a){ 
    A = function (b) { 
    console.log(a + b++); }; console.log(a++); } A(1); //结果:1 A(2); //结果:4 

图解:

image-20210917095614772

解析:

  1. 先有全局执行上下文EC(G),然后有全局变量的环境VO(G),a,b,function A都属于全局的变量。
  2. 给a、b创建基本数据类型值并赋值,但A是个函数,函数是引用类型的值,所以会开辟一个函数堆,有个地址AAAFFF000,然后将这个地址和函数A关联在一起。
  3. 创建A函数的时候会声明一个作用域 [[scope]]:EC(G)(在全局作用域下),形参是a,里面有代码字符串…
  4. A(1)执行。函数执行就是把函数里面的代码执行。那每个函数的执行都会形成一个全新的私有上下文(环境EC(A1))。AO(A1)是私有变量对象。函数执行会先初始化作用域链:
    (左边是自己的上下文,右端是A这个函数创建时所在的作用域即为全局作用域EC(G))。在代码执行过程中遇了一个变量,首先看是否是自己的私有变量,如果是自己的私有变量则找私有的,否则就找其函数所在的作用域EC(G)中的全局变量。此时的进行形参赋值 a=1(形参变量也是私有变量,让a和1进行关联)。让代码执行,A = function(b){....}(这时要创建一个新函数堆内存(BBBFFF000),声明作用域:[[scope]]:EC(A1)。形参是b,代码字符串”console.log(a+b++)”),因为A不是EC(A1)私有的,故去EC(G)里面找,那么就要修改原来A对应的函数地址(将AAAFFF000改为BBBFFF000,即把全局下的A修改为BBBFFF000)。接着执行console.log(a++)(先输出a=1,然后再++,即做完后修改a的值为2,这里的a是EC(A1)里面的)。执行完毕。(此时EC(A1)不能被释放,因为全局中A的地址为BBBFFF000,占用了EC(A1)中的内容,这就形成了闭包)
  5. A(2)执行。此时的A对应的为BBBFFF000,也就是要进行那个小函数的执行(即执行 console.log(a + b++))。这时又会形成一个全新的私有上下文EC(A2)。作用域链:
    。形参赋值:b=2。代码继续执行:a + b++,因为当前上下文中没有a,故往上级上下文EC(A1)找,有a,此时a=2。b在自己的上下文EC(A2)中有,所以b=2,故a+b++=4,然后b++,修改当前上下文中的b为3。执行完毕。(因为执行完后,这个EC(A2)上下文中没有东西被外部东西占用,所以默认就会被释放掉)

三、总结

自己的错误点

A = function (b) { 
    console.log(a + b++); }; 

会把上面那个代码看成是立即执行,其实并不是。老是犯这个错误,谨记!!!

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

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

(0)
上一篇 2026年3月26日 下午7:36
下一篇 2026年3月26日 下午7:36


相关推荐

  • 扣子空间+自定义MCP,我的学习搭子来了!(附邀请码)

    扣子空间+自定义MCP,我的学习搭子来了!(附邀请码)

    2026年3月12日
    2
  • 基于java的毕业设计论文题目_毕业论文国外参考文献怎么找

    基于java的毕业设计论文题目_毕业论文国外参考文献怎么找第一份资料:Kafka实战笔记Kafka入门为什么选择KafkaKarka的安装、管理和配置Kafka的集群第一个Kafka程序afka的生产者Kafka的消费者深入理解Kafka可靠的数据传递Spring和Kalka的整合Sprinboot和Kafka的整合Kafka实战之削峰填谷数据管道和流式处理(了解即可)Kafka实战之削峰填谷第二份资料:ActiveMQ实战笔记ActiveMQ入门ActiveMQ的安装原生JMS

    2022年9月30日
    4
  • linux无锁编程[通俗易懂]

    linux无锁编程[通俗易懂]简单的笔记,未完待续一道题:无锁化编程有哪些常见方法?针对计数器,可以使用原子加只有一个生产者和一个消费者,那么就可以做到免锁访问环形缓冲区(RingBuffer)RCU(Read-Copy-Update),新旧副本切换机制,对于旧副本可以采用延迟释放的做法 CAS(Compare-and-Swap),如无锁栈,无锁队列等待解析:一、RCU   

    2022年6月9日
    57
  • 令牌桶算法

    令牌桶算法一 什么是令牌桶算法令牌桶算法是比较常见的限流算法之一 要点如下 所有的请求在处理之前都需要拿到一个可用的令牌才会被处理 根据限流大小 设置按照一定的速率往桶里面添加令牌 桶设置最大的放置令牌限制 当桶满时 新添加的令牌就被丢弃或者拒绝 请求到达后首先要获取令牌桶中的令牌 拿着令牌才可以进行其他的业务逻辑 处理完业务逻辑之后 将令牌直接删除 令牌有最低限额 当桶中的令牌达到最低限额的时候 请求处理完之后不会删除令牌 以此保证足够的限流

    2026年3月26日
    3
  • 完全理解icmp协议

    完全理解icmp协议1.ICMP出现的原因在IP通信中,经常有数据包到达不了对方的情况。原因是,在通信途中的某处的一个路由器由于不能处理所有的数据包,就将数据包一个一个丢弃了。或者,虽然到达了对方,但是由于搞错了端口号,服务器软件可能不能接受它。这时,在错误发生的现场,为了联络而飞过来的信鸽就是ICMP报文。在IP网络上,由于数据包被丢弃等原因,为了控制将必要的信息传递给发信方。ICMP协议是为了辅助IP…

    2022年7月12日
    26
  • 排序二叉树-删除节点

    排序二叉树-删除节点前面(https://blog.csdn.net/jsjsjs1789/article/details/106772632),我们已经了解了什么是排序二叉树以及排序二叉树的遍历和添加元素,现在我们一起来看一下,排序二叉树是如何删除元素的。packagexmht.datastructuresandalgorithms.datastructure.binarysortTree;/***@authorshengjk1*@date2020/6/15*/publicclassB

    2022年7月25日
    10

发表回复

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

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