JavaScript三座大山:1.原型与原型链;2.作用域及闭包;3.异步和单线程。这次本文谈谈我对作用域及闭包的理解,如何一步步挖走这个代码路上的大山之一。
一.作用域(scope)
1.作用域是一个不可理喻的熊孩子?
作用域,不仅仅是变量和函数的存储的空间,同时它自带一些规则来规范引擎如何找到这些变量和函数。作用域也可以很好的保护其中的变量和函数,避免它们被随意访问和修改。在ES6到来之前,作用域分为全局作用域和函数作用域。
2.在哪一时间、是怎么出生的?
首先,预编译在开始时会创建一个全局作用域GO(Global Object)
- 第一步:记录下全局里的所有变量声明,变量名为key,value为undefined存储在对象里;
- 第二步:找到所有的函数声明,函数名为key,函数体为value存储在对象里。
function foo () {
function a () {
var aa = 123;
}
var b = 100;
a();
console.log(b)
}
var glob = 100;
foo()
GO: {
glob : undefined,
foo: function foo () {...}
}
遇到函数需要执行的前一刻,会给执行的工作创建一个新的作用域AO(Activation Object)
- 第一步将函数内所有的形参和变量声明储存到ao对象中,value为undefined;
- 第二步:将形参和实参进行统一;
- 第三步:所有的函数声明的函数名作为ao对象中的key,函数整体内容作为value,存储到ao对象中。
这就是除了全局作用域外其他函数作用域产生的时间及如何产生的。
AO: {
b : undefined,
a : function a () {...}
}
二.作用域链(scopr-chain)
在程序预编译时,执行代码前一刻产生的一个个作用域以链式链接的方式呈现,叫做作用域链,引擎在查找作用域里的变量、函数,会从该所处的作用域一级级向上查找父级作用域,而不会在它下一级的作用域去查找。上面的示例,全局作用域下存在一个AO这个子作用域,形成了一个简单的作用域链。
三.闭包(closure)
初学的时候,只知道“闭包”两个字,却不知道在我们code的时候,见到的很多东西就是闭包。搞懂了闭包,就有一种“就它叫闭包?”的错愕感呢。不过在弄懂闭包之前,需要明白JavaScript存在回收机制,以节省内存,在一行代码执行完以后则会进行回收。
回收,不是无效化这行代码,而是收掉这行代码产生的作用域,直到下次这行代码再次被执行,会重新产生一个新的作用域。只要这行代码还没执行完,由它产生的作用域也不会消失!!这就是闭包产生的原因。
那么有没有办法能让代码处于没被执行结束的状态呢?聪明的读者肯定是能想到欸,有的,也是很常见的一种,就是赋值。
function a(){
function b () {
var bbb = 234
console.log(aaa) //看上去应该报错,实际上有值,这就是闭包
}
var aaa = 123
return b // b 出生在a里面,但是被保存出去了
}
var demo = a() //先demo声明 后执行函数a()
demo()
GO: {
demo: undefined,
a: function a () {...}
}
aAO: {
aaa: undefined,
b: function b() {...}
}
bAO:{
bbb: undefined
}
函数a()执行之后,把aAO里的函数b返回给GO下的dem。按理说执行完aAO就应该被回收,但是全局作用域下的demo被赋值为函数b,它的执行保证了a处于执行未完成的状态从而aAO未被回收,所以aAO作用域里产生的变量和函数都能被子作用域bAO访问、打印出aaa的值,这就是闭包的魅力!
1.闭包让人觉得“熊”的原因
对于初学者,因为它的抽象以及js原理知识的匮乏,弄不懂便觉得厌烦,很正常。当你下定决心弄懂,逐渐在学习前端的道路并上正轨,明白它的出生机制。成也作用域,败也作用域,这种基因上带来的缺陷,只有高手能把它玩弄于股掌之间。
正因为作用域的未被回收,造就了闭包,同时作用域占用了内存,闭包的过多创建,若未能及时回收,最终会造成内存泄露。
2.闭包另一方面觉得可爱的缘由
它的产生,让人们有了更多的启发
-
- 实现公有变量(企业的模块化开发),如:函数累加器;
-
- 做缓存(父级作用域下产生两个同级作用域,即使一个被回收,另外一个也已经缓存);
-
- 私有化变量(封装);
-
- 模块化开发, 防止污染全局变量。这些都是很常见地被运用在代码中。
四.最后
以上都是最近学习所感,记录下自己代码路上的一点见解心得。往往在理解一个东西的时候,需要理解别的知识点,这个知识点又要用到别的知识,最终回到原理机制与基础,学无止境吧,希望永远怀着一颗学徒的心。