0.写在前面:
下学期就打算去实习了,这段时间要密集接收考试和面试的捶打,计网和软工就没有办法为大家继续贡献开源内容了,明年九月份之前的更新内容将会以前端,人工智能,和工程设计为基础, 很抱歉啦,不过我还是希望我这一年来的努力可以帮到一些人.虽然自己这一年过的浑浑噩噩的, 也失去了很多东西.................
嘛, 对了, 联系我的话可以csdn私信,也可以加我的各种联系方式,尤其是需要资源的朋友们.....
后面会根据一些面试题目以及一些东西构建这样一个专栏,记录一些琐碎的知识点.
今天在做题的时候,偶然遇到了一个问题,这个正好是之前没有了解的太好
其实这个题很简单,没有什么算法上的难度,但是需要理解一点,也就是closure,这个题目已经写好了,但是还需要点别的理解才对.
1.什么是闭包:
先说说闭包的官方定义,根据MDN所说:‘闭包(closure)是一个函数以及其捆绑的周边环境状态(lexical environment,词法环境)的引用的组合。换而言之,闭包让开发者可以从内部函数访问外部函数的作用域。’
闭包(closure)是一个函数以及其捆绑的周边环境状态(lexical environment,词法环境)的引用的组合。换而言之,闭包让开发者可以从内部函数访问外部函数的作用域。说人话就是,在函数生成的时候,将函数以及周边的变量打包成一个独立的"包", 这样函数在调用包内的属性的时候,得到的是一个相对比较独立的属性.
我承认这个样确实抽象,别急,慢慢解释
2.词法作用域:
在阐述闭包之前,先解释一下js中的一个重要概念,词法作用域:
词法作用域是指在代码编译阶段确定的作用域规则,它确实是整个 JavaScript 中的一种具体的作用域规则。词法作用域决定了变量在哪个作用域中可见,它的范围在代码编译时就确定,并且在代码执行期间保持不变。又被叫做静态作用域,例如作用域链, var的变量提升,都和词法作用域规定的内容有关.
词法作用域指的并不是具体的某个作用域,而是js中关于作用域规则的统称, 也可以指代某个作用域. 例如我可以在不同情况下,称呼"全局""函数""块"都是一个"词法作用域"
3.闭包的效果展示
其实题目中已经能展示的差不多了,这里重新构建一个代码进行效果展示:
function test(){let funct=0;const test1=()=>{console.log(funct,"-->",++funct);}return test1;
}
我们创建了一个test函数,换句话说,我们构建了一个函数作用域
funct变量,是在这个作用域中的
test1函数,展示funct的变化
最后返回test1这个函数,也就是生成这样一个函数
这算是最经典的闭包案例了
接下来我们要做的东西就是,根据这个函数创建两个新的函数
const a=test();
const b=test();
a和b各自都是生成的一个test1函数
接下来我们展示这个情况
console.log('a的变化')
a();
a();console.log('b的变化')
b();
如图所示
这样的效果其实可以这样子理解:
在生成一个函数的时候,函数和同一个词法作用域内的属性,可以"打包"在同一个闭包内部
换句话说,我们调用的不是函数,而是这个闭包.
我知道不好理解,所以画图
其实闭包就是这么简单的东西,但是肥肠可贵的一点是, 闭包的存在允许一些函数持有自己的独立属性! 这一点在java等中是通过private实现的,在js中则需要我们结合对应的语法,使用设计模式实现,有一个很经典的设计模式我们需要讨论,不过在这之前,我想很多人应该会有一个问题
闭包这个打包的范围究竟是哪里?
4.闭包的打包范围究竟是多少
在这里我们就不做实验了,直接说结论:
闭包的打包范围,就是函数生成位置的词法作用域!
在3的案例中,我们的函数test1是在test函数内部生成的,所以生成的函数打包的结果就是一整个test函数的作用域,每次生成一个新的函数,就创建这样一个闭包.可以理解为,闭包内部就是这些东西
为什么要提及这个?其实很多人不在乎这一点
但是闭包本身是一个很复杂的概念,换句话说,在实际应用领域(下面会有所提及),大家遵守一致的默契. 但是深究起来每个人都有自己的理解.
在这里我斗胆设置一个"私密打包"的功能名称给闭包, 打包这样一个私有的区域,范围就是函数生成时候所在的词法作用域.
闭包的独立范围仅限于函数本身生成时所在的词法作用域以及外部作用域。它并不包括全局作用域。
当一个函数被定义时,它会创建一个闭包,其中包含了函数自身以及函数所在的词法作用域中的变量。这个闭包可以在函数定义的词法作用域之外被调用,并且仍然可以访问和使用这些变量。
闭包的独立范围是相对于函数生成时所处的词法作用域而言的,它并不扩展到全局作用域。
而闭包本身,根据MDN文档的解释,是"可以通过作用域访问到全局作用域,因此闭包的范围是沿着作用域一直向上的",不同的人有不同的理解.
5.经典案例:私有属性
在js中是不存在和java一样完善的类的,这就代表我们很难像Java一样构建一个完整的,稳定的类,某种意义上来说这也算是js没有发展成气候的原因?
但是私有属性在MDN上有一个经典的案例,在这里我们不多解释了,因为代码不是我写的
解释一下这个代码:
在这个代码中,我们使用立即执行函数返回了三个函数,组合成立一个对象.
这个对象里的三个函数能调用函数作用域内的属性,这就很神奇的实现了私有属性
6.为什么不这样做:性能问题
实际上,在一个函数内创建以及生成别的函数,本身其实是很损耗性能的行为,因此在实际中,我们宁可让代码的安全交给程序员来维护,而不是损害性能,