尝试使用费曼学习法,所以不会说一些专业术语,都是我自己对作用域和闭包的理解,更专业的解释可以看《你不知道的JavaScript(上卷)》
一个一个房间,大的房间中可以包含小的房间,但有一个最大的房间,也就是全局作用域。
小房间的人们如果想看书,可以先在自己的房间中找找,如果找不到也可以去大房间中找,直到最大的那个房间,但要注意,不能跑到大房间中其他人的小房间找。
对于用不同方式编写的书,会有不同的效果,var
型书籍除非在函数造的房间中编写,否则都会算作整个房子的大房东window
的;let
和const
型书籍在编写后就只属于自己小房间了。
如果有一本书,大房东那也有另外一本,这时即可以按上面的路线找到房子里的书,也可以直接通过window.val
向大房东借。
找到书后可以在书中随便做笔记了,但之后要立刻还回远处,供别人使用,但书的质量就很难保证了。
当一个小房子中不再想看书,不再有什么活动时,就会被拆除,包括房间中的所有东西。当然,小房间里的活动也算大房间的。 要注意的是,函数造的房间一般不会被拆除,因为有钥匙的人就可以进去,除非之后真的没有人想到这房间里了。
现在可以停下来想想,上面的这些机制会有什么奇妙的效果!
由于进入函数房间只需要有钥匙就可以,那么当配一把钥匙拿到外面的时候。外面的人就可以通过钥匙直接进到函数房间,而在函数房间就可以自由的去大房间找书。函数房间对外面房间的记忆,就是闭包。
示例
下面列举具有上述表述效果的代码,最后一个是闭包的简单应用,都非常简单,就不进行解释了
let a = "global a";
{
let b = "first b";
{
let a = "second a";
console.log(a); //second a
}
{
console.log(a); //global a
console.log(b); //first b
console.log(c); //ReferenceError: c is not defined
}
}
var a = "window a";
{
let a = "first a";
{
let a = "second a";
var b = "window second b";
console.log(a); //second a
console.log(window.a); //window a
}
{
console.log(a); //first a
console.log(window.a); //window a
console.log(window.b); //window second b
}
}
function func(){
var a = "func a";
console.log(a); //func a
}
func();
console.log(a); //ReferenceError: a is not defined
let a = "global a";
function func(){
let b = "func b";
function foo(){
console.log(a);
console.log(b);
}
return foo;
}
let Foo = func();
Foo(); // global a; func b