首页 文章详情

作为一名前端搬砖人,提起闭包我就心梗。

勾勾的前端世界 | 375 2021-01-15 18:40 0 0 0
UniSMS (合一短信)

(。・∀・)ノ゙嗨,我是你稳定更新、持续输出的勾勾。



作为一名前端搬砖人,提起闭包我就心梗。


我听得最多的一句话就是,“闭包,只可意会不可言传”。


伴随一周最开心的一刻(明天周末!),我们一起来谈谈这个十分抽象的话题。


简单来说,闭包就是指有权访问另一个函数作用域中的变量的函数。最常见的形态就是在一个函数的内部创建另一个函数。


结构

1) 外部函数的返回结果是一个函数,暂且称为内部函数。

2) 内部函数中使用了外部函数中的变量(成员)。


现象

1) 外部函数执行结束后,被内部函数使用的变量(成员)不会被销毁释放。

2) 生命周期:在整个代码执行结束时才销毁。

3) 作用域:只能在函数内部访问。


目的

1)每次去执行返回的内部函数,都可以使用该变量(成员)。


并且该变量(成员)的值可以变化,也就是说,该变量(成员)可以在函数多次执行过程中保存状态。


在其它一些语言中称为静态变量。


例:记录函数调用次数。


2)该变量可以被返回的内部函数访问。但是外部其它代码无法访问,防止意外修改,起到了保护作用。


Demo

例1:

// 闭包function makeFn() {    let msg = '函数作为返回值'    return function() {        console.log(msg)  // 内部函数访问外部函数的 msg    }}
// 外部函数 makeFn 执行完, 应清理所有, 但其 msg 被 fn 使用, 所以 msg 不会销毁const fn = makeFn()fn() // 第一,msg 可以在 fn 中反复使用console.log(msg) // 第二,msg 在外部这里是访问不到的,它被保护了起来


例2:

// 闭包function once (fn) {    let done = false    return function () {        if (!done) {   // 使用(引用)了外部函数的变量            done = true            fn.apply(this, arguments)        }    }}
let pay = once(function (money) { console.log(`支付: ${money} RMB`)})
pay(5)pay(5)


例3:

/*  求数字的平方    pow(5, 2)    pow(4, 2)  可以把 2 固定下来*/ function makePower(power) {    return function (number) {        return Math.pow(number, power)    }}
// 返回 求平方 的函数let power2 = makePower(2)console.log( power2(4) ) // 4的平方等于16console.log( power2(5) ) // 5的平方等于25
// 返回 求立方 的函数let power3 = makePower(3)console.log(power3(4)) // 4的立方等于64console.log(power3(5)) // 5的立方等于125
/* 我的理解: power 作为参数,理解为外部函数的局部变量 内部函数中引用了它,内部函数被返回 所以,这是闭包的结构 函数参数的灵活性不同, 有的经常变, 有的偶尔变 可以把多参数的函数, 细粒度一些, 如上面代码*/
/*Call Stack 调用栈Scope 作用域 Local 局部作用域 Global 全局作用域 通过var定义的变量会在全局 Script 通过let定义的变量可以在这个位置看到Closure (makePower) 说明这个闭包引用了 makePower 外部函数中的变量(成员) 内部函数执行时, 才可以看到闭包相关内容, 即看到它所引用外部函数中的内容*/


例4:

/*  不同级别员工的工资  生成计算工资的函数. 不同级别员工 基本工资不同     基本工资 base         12000, 15000      绩效工资 performance*/function makeSalary (base) {  return function (performance) {    return base + performance  }}
// 基本工资为 12000 的 工资计算函数let salaryLevel1 = makeSalary(12000)// 基本工资为 15000 的 工资计算函数let salaryLevel2 = makeSalary(15000)
console.log(salaryLevel1(2000)) // 总工资 14000console.log(salaryLevel2(3000)) // 总工资 18000


不管你的理解如何,只要你能写出闭包的案例,就已经一脚踏入了前端的世界。


周末快乐(●'◡'●)。


推荐阅读:

异步无处不在:同步模式和异步模式(一)

异步无处不在:回调函数(二)

异步无处不在:Promise 破除“回调地狱”(三)

异步无处不在:终极解决方案(四)

异步无处不在:Generator 异步方案(五)

Redux 续集 | 如何搞定其中的异步操作?

技术人年度总结 | 2020,注定不平凡

是我 Web 端配不上阿里了。

前端人因为 Vue3 的 Ref-sugar 提案打起来了!


点点“”和“在看”,保护头发,减少bug。

good-icon 0
favorite-icon 0
收藏
回复数量: 0
    暂无评论~~
    Ctrl+Enter