2024年最全【面试题】对闭包的理解?什么是闭包?,2024年最新前端面试必备

JavaScript

  • js的基本类型有哪些?引用类型有哪些?null和undefined的区别。

  • 如何判断一个变量是Array类型?如何判断一个变量是Number类型?(都不止一种)

  • Object是引用类型嘛?引用类型和基本类型有什么区别?哪个是存在堆哪一个是存在栈上面的?

  • JS常见的dom操作api

  • 解释一下事件冒泡和事件捕获

  • 事件委托(手写例子),事件冒泡和捕获,如何阻止冒泡?如何组织默认事件?

  • 对闭包的理解?什么时候构成闭包?闭包的实现方法?闭包的优缺点?

  • this有哪些使用场景?跟C,Java中的this有什么区别?如何改变this的值?

  • call,apply,bind

  • 显示原型和隐式原型,手绘原型链,原型链是什么?为什么要有原型链

  • 创建对象的多种方式

  • 实现继承的多种方式和优缺点

  • new 一个对象具体做了什么

  • 手写Ajax,XMLHttpRequest

  • 变量提升

  • 举例说明一个匿名函数的典型用例

  • 指出JS的宿主对象和原生对象的区别,为什么扩展JS内置对象不是好的做法?有哪些内置对象和内置函数?

  • attribute和property的区别

  • document load和document DOMContentLoaded两个事件的区别

  • JS代码调试

  • 开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

大厂面试题分享 面试题库

后端面试题库 (面试必备) 推荐:★★★★★

地址:前端面试题库

闭包的背景

由于js中只有两种作用域,全局作用域和函数作用域,而在开发场景下,将变量暴露在全局作用域下的时候,是一件非常危险的事情,特别是在团队协同开发的时候,变量的值会被无意篡改,并且极难调试分析。这样的情况下,闭包将变量封装在局部的函数作用域中,是一种非常合适的做法,这样规避掉了被其他代码干扰的情况。

闭包的使用

下面是一种最简单直接的闭包示例

//妈妈本体functionmother(){
    //口袋里的总钱数let money = 100//消费行为returnfunction (pay){
        //返回剩余钱数return money - pay
    }
}
//为儿子消费let payForSon = mother()
//打印最后的剩余钱数console.log(payForSon(5))
复制代码

为了便于理解,我们将外部函数比喻为妈妈本体,里面保存着总钱数这个变量和消费这个行为,通过创建为儿子消费的这个行为对象,然后执行这个行为花费5元,返回剩余的95元。

这个就是为了将变量money保存在mother本体内而避免暴露在外部的全局环境作用域中,只能通过mother()创建消费行为来影响money这个变量。

由此可以归纳总结使用闭包的三个步骤

  1. 用外层函数包裹变量,函数;

  2. 外层函数返回内层函数;

  3. 外部用变量保存外部函数返回的内层函数

目的是为了形成一个专属的变量,只在专属的作用域中操作。

上述的闭包代码示例中,有一个缺陷的场景是,在后续不需要money变量的情况下,没有释放该变量,造成内存泄露。原因是payForSon这个函数的作用域链引用着money对象,解决的办法是将payForSon = null就可以释放方法作用域,进而解除对money的引用,最后释放money变量。

闭包的扩展

函数柯里化


在开发的场景中,有时需要通过闭包来实现函数的柯里化调用。调用示例如下

alert(add(1)(2)(3))
复制代码

这种连续的传参调用函数,叫做函数柯里化。

通过闭包的实现方式如下

functionadd(a){
    //保存第一个参数let sum = a
    functiontmp(b){
        //从第二个函数开始递加
        sum = sum + b
        //返回tmp,让后续可以继续传参执行return tmp
    }
    tmp.toString = function(){
        return sum
    }
    //返回加法函数return tmp
}
alert(add(1)(2)(3))
复制代码

下面我们来一步步分析,

  1. add(1)执行时,保存第一个参数到sum变量中,返回tmp函数

  2. add(1)(2)执行等于tmp(2),将2的值加到了变量sum上,返回tmp函数本身

  3. add(1)(2)(3)执行等同于上述步骤的加到比变量sum上,返回tmp函数本身

  4. alert(add(1)(2)(3))执行时,alert需要将值转为string显示,最后的tmp函数执行tmp.toString,返回sum的值。

矩阵点击应用


该例子的demo代码在我的github上,可以自行取阅

需求:在一个4*4的矩阵方块中,实现点击每个按钮时记录下各自的点击次数,相互之间互不干扰。

思路:在按钮事件中使用闭包,创建独立的存储变量空间。

注意:下列的方案1到方案3是逐次演进的优化方案,需要按照方案标号的次序逐层理解,更有利于理解最终的优化方案

方案1
<div id="container"></div>
...
let container = document.getElementById('container')
for (let r = 0; r < arr.length; r++) {
    for (let c = 0; c < arr[r].length; c++) {
        let cell = document.createElement('div')
        cell.innerHTML = `(${r},${c})`
        container.append(cell)
        cell.onclick = (function () {
            let n = 0
            return function () {
                n++
                cell.innerHTML = `点${n}`
            }
        })()
    }
}
复制代码

在每个按钮上通过onclick绑定闭包方法,存储操作独立的n变量,这样就可以单独记录每个按钮的点击次数

缺点:这样做有一个不足的地方是,外部无法获取内部的n变量,不能实现与外部的交互,比如按钮间的相互影响。

方案2

为了改善方案1的缺点,我们引入外部数据arr来操作管控按钮点击数。 代码示例如下:

let arr = [
            [0, 0, 0, 0],
            [0, 0, 0, 0],
            [0, 0, 0, 0],
            [0, 0, 0, 0],
        ]
let container = document.getElementById('container')
for (let r = 0; r < arr.length; r++) {
    for (let c = 0; c < arr[r].length; c++) {
        let cell = document.createElement('div')
        cell.innerHTML = `(${r},${c})`
        container.append(cell)
        cell.onclick = (function (r, c) {


##### 框架相关

原生JS虽能实现绝大部分功能,但要么就是过于繁琐,要么就是存在缺陷,故绝大多数开发者都会首选框架开发方案。现阶段较热门是React、Vue两大框架,两者工作原理上存在共通点,也存在一些不同点,对于校招来说,不需要两个框架都学得特别熟,一般面试官会针对你简历中写的框架进行提问。

在框架方面,**生命周期、钩子函数、虚拟DOM这些基本知识是必须要掌握的**,在学习的过程可以结合框架的官方文档

**[开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】](https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0)**

**Vue框架**

>**知识要点:**
>**1. vue-cli工程**
>**2. vue核心知识点**
>**3. vue-router**
>**4. vuex**
>**5. http请求**
>**6. UI样式**
>**7. 常用功能**
>**8. MVVM设计模式**

![](https://img-blog.csdnimg.cn/img_convert/aef78d390ace4fa5520e8a8479471d8f.webp?x-oss-process=image/format,png)


**React框架**

>**知识要点:**
>**1. 基本知识**
>**2. React 组件**
>**3. React Redux**
>**4. React 路由**

![](https://img-blog.csdnimg.cn/img_convert/4286a6a4f915ef5f2937190b13fd28f4.webp?x-oss-process=image/format,png)



3. vue-router**
>**4. vuex**
>**5. http请求**
>**6. UI样式**
>**7. 常用功能**
>**8. MVVM设计模式**

[外链图片转存中...(img-Oyn4MSif-1715668745204)]


**React框架**

>**知识要点:**
>**1. 基本知识**
>**2. React 组件**
>**3. React Redux**
>**4. React 路由**

[外链图片转存中...(img-ThUyfTkf-1715668745205)]



  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值