历时一个月,我终于搞懂了闭包
我终于搞懂了js里面的闭包
一提到闭包,大家就会想起JavaScript中的闭包,没错,闭包是JavaScript的一大特色,这是因为有了闭包,让JavaScript可以做一些特别的工作。
但是闭包对于很多人来说很亲切却又很陌生。为什么呢? 因为闭包在JavaScript中非常常见,但是呢闭包又是JavaScript中的一大难点,被称作JavaScript里面的三座大山。
今天我给大家带来我对闭包的理解:
1.准备工作
在了解闭包之前,我们需要知道两个东西:
- 作用域
- 函数在定义时的一些小知识
1.1作用域
在JavaScript中,定义变量时所在的作用域,决定了这个变量的可见性。
JavaScript中有两种作用域:全局作用域与局部作用域。
- 全局作用域:在这里定义的变量,整个代码都可以访问到这变量。
- 局部作用域:在这里定义的变量,在该局部作用域和上级作用域可以访问到
也就是说,全局作用域下可以有多个局部作用域,在某个局部作用域里面也可以存在多个(子)局部作用域。
我们可以这样理解,全局作用域是祖先作用域,剩下的作用域可以被分为子局部作用域、孙局部作用域、、、、、、
就像这样:
当我们需要查找一个变量的值的时候,我们JavaScript的引擎就会这样去寻找:
如果是在局部作用域查找该变量的值,JavaScript首先会在本局部作用域查找这个变量,如果查找到,就使用该变量;如果没有找到,就会往上一级作用域查找,依次类推。这就是我们所说的就近原则。
我么可以发现:查找变量都是向本作用域或者上级作用域查找。而不会向下级作用域查找,这是因为我们不能访问下级作用域的变量。但是闭包的出现,就能解决这个问题。
不着急,我们慢慢往下看。
1.2函数定义时的一些小知识
我这里只讲述函数定义时作用域的知识:
函数在定义的时候就会与定义时所在的变量作用域绑定,就比如函数在全局作用域下定义,那么这个函数就一直处在全局作用域;如果函数在某一个局部作用域下定义,那么该函数就与这个局部作用域绑定。
并且在函数内部也会形成一个局部作用域,这里面定义的变量只能在函数内部使用。
2.上正菜:闭包
在了解了前面的知识之后,我们就可以开始我们今天的正菜了:闭包。
前面我们知道函数内部是一个局部作用域,并且在函数外部是不能访问到函数内部的变量的。
function f(){
let a = 2;
console.log(a);
}
f();// 2
console.log(a);// 报错 变量a没有定义
有了闭包之后,这一切都不一样了。闭包:就是能够读取其他函数内部变量的函数。是的,你没有看错,闭包其实是一个函数。
我们先弄一个闭包出来,然后我们再来讲讲闭包是怎么实现的。
function f1(){
let a = 10;
let b = 20;
function f2(){
return a;
}
return f2();
}
let c = f1();
console.log(c);// 10
很神奇吧,在函数外部,我们居然读取到了函数内部变量的值。
这是因为,f1
函数内部定义了一个f2
函数,因为f2
函数是在f1
内部定义的,多以f2
的作用域就为f1
局部作用域里面的又一个子局部作用域。
根据前面我们的铺垫可知:
- 在
f2
函数作用域内可以访问到f1
的变量。
所以当f2
作为f1
的返回值的时候,就把f2
能访问到的变量的值也返回回去了。这样就导致,外部调用f1
函数的时候,返回一个f2
函数,f2
函数里面又可以访问到f1
内部的变量。最终f1
函数外部也能访问f1
内部的变量了。
有点绕,但是闭包就是这样一个原理。
2.1闭包作用
- 闭包可以读取函数内部的变量
- 闭包可以使得变量的值始终保存在内存中
针对第一点,闭包可以实现对象的某些私有方法。 第二点,这提醒我们要慎用闭包,虽然它很灵活,但是不小心开发者就会写一个闭包出来,有可能会造成内存泄露。
总结
一直在路上,2023新的一年,新的开始。坚持不懈的学习,终会有成功的那一天。
转载自:https://juejin.cn/post/7183600879231041597