2024年Web前端最新【面试题】对闭包的理解?什么是闭包?,我的前端美团求职之路

本文通过阿里面试题为例,探讨了JavaScript中add函数的递归应用,展示了闭包在矩阵点击应用中的使用以及如何通过bind函数实现作用域绑定。文章强调了前端开发面试中常考知识点的重要性,并分享了系统化的复习路线。
摘要由CSDN通过智能技术生成

最后

小编综合了阿里的面试题做了一份前端面试题PDF文档,里面有面试题的详细解析

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

虽只说了一个公司的面试,但我们可以知道大厂关注的东西并举一反三,通过一个知识点延伸到另一个知识点,这是我们要掌握的学习方法,小伙伴们在这篇有学到的请评论点赞转发告诉小编哦,谢谢大家的支持!

复制代码


下面我们来一步步分析,


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](https://bbs.csdn.net/topics/618166371)上,可以自行取阅


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


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


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


#### 方案1



... 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) {
            return function () {
                arr[r][c]++
                cell.innerHTML = `点${arr[r][c]}`
            }
        })(r, c)
    }
}
复制代码

参照方案1 ,改动点包含两个

  • 新增arr二维数组来记录点击数,这样可以达到与外部交互的目的

  • onclick绑定的事件新增r,c两个参数,并且执行时传参进入,这样就可以把行列参数传递到方法内部(onclick的执行环境作用域与r,c所在的环境不一致,所以无法直接使用)

这样改进完以后,外部可以通过操作arr来与每个按钮的点击次数进行交互。

缺点:这样会将arr暴露在全局作用域下(可以在console控制台访问到),很容易被其他人或者模块误操作,也不利于封装

方案3

基于方案2的改进实现为,用一个立即执行的函数包裹住整个执行代码,这样就构建了一个函数作用域来封装arr变量为私有。代码如下:

(function () {
        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) {
                    return function () {
                        arr[r][c]++
                        cell.innerHTML = `点${arr[r][c]}`
                    }
                })(r, c)
            }
        }
    })()
复制代码

这样一个相对完整的按钮点击次数的方案就完成了。

使用call实现bind


这个需要有call和bind的使用知识的前提,可以自行百度哈

废话不多说,直接上代码

Function.prototype.bind = function(obj){
    console.log('调用自定义bind函数');
    //保存当前函数对象let fun = this//去除第一个obj参数,并且转换为js数组let outerArg = Array.prototype.slice.call(arguments,1)
    returnfunction(){
        //将arguments转为js数组let innerArg = Array.prototype.slice.call(arguments)
        //汇总所有参数let totalArg = outerArg.concat(innerArg)
        //调用外部保存的函数,并且传参
        fun.call(obj,...totalArg)
    }
}

//调用示例let zhangsan = {name:'wawawa'}
functiontotal(s1,s2){
    console.log(this.name + s1 + s2);
}
let bindTotal = total.bind(zhangsan,100)
bindTotal(200)
复制代码

重写函数类的bind函数,

  1. 先将函数对象(也就是下面示例中的total函数)保存在fun变量中,等于闭包外层保存了fun,obj以及其他绑定的参数(由于arguments是类数组对象,需要转换为数组,且去除第一个函数obj);

  2. 然后返回匿名函数,在匿名函数中,将外部和内部的参数进行转换和拼接;

  3. 最后通过fun.call(obj,…totalArg),调用保存的函数对象fun,并且通过call来实现传递绑定的作用域obj,和其他参数totalArg

注意:

最后

其实前端开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

这里再分享一个复习的路线:(以下体系的复习资料是我从各路大佬收集整理好的)

《前端开发四大模块核心知识笔记》

最后,说个题外话,我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

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

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在IT学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值