闭包基本知识汇总
一、什么是闭包?
闭包是指有权限访问另一个函数作用域中的变量的函数,在Javascript中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成 “定义在一个函数内部的函数” 。所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。闭包是一种JavaScript特有的一种函数结构(一种嵌套用法)。
二、闭包的特性:
-
函数嵌套:函数嵌套函数,内层函数使用了外层函数的变量(参数);
-
局部变量:在函数内定义具有共享意义的局部变量;—— 函数作用域
-
外部使用:内层函数被返回到外部 在外部调用,外部可通过这个内层函数访问声明在函数中的局部变量,而此变量在外部是无法通过其他途径被访问的;—— 这里的“返回”包括但不仅限于return;
-
词法环境不同:每个闭包都有它自己的词法环境;—— 词法作用域:根据源代码中声明变量的位置来确定该变量在何处可用。
-
变量不被回收:外层函数中,被引用的变量(参数)不会立即被垃圾回收机制回收;
三、闭包的作用:
-
使用闭包,可以延长局部变量的生命周期,由于内层函数使用了外层函数的变量,导致外层函数在执行结束后,变量没有被回收;
-
使用闭包,可以隔离作用域,避免被全局污染; ——
😭(window) => { … })(window);
-
使用闭包,可以保护具有共享意义的变量, 为其提供相关的操作接口(function),可以用来模拟私有方法
四、闭包的优点:
- 数据共享:使用闭包,在外层函数中,被引用的变量(参数)不会立即被垃圾回收机制回收,会一直被保存在内存中,实现数据共享;
- 数据私有化:使用闭包,在函数外部能够访问到函数内部的变量,但是它在外部是无法通过其他途径被访问的,实现数据私有化;
五、闭包的缺点:
- 通过使用闭包,外层函数中被引用的变量(参数)不会立即被垃圾回收机制回收,会一直被保存在内存中,不会被释放,占用内存严重,造成内存泄漏,甚至栈溢出。
内存泄漏:由于疏忽或错误造成程序未能释放已经不再使用的内存
可能会导致栈溢出的场景:递归、自调用、超深循环等
六、简单的面试题
请编写一个简单的闭包
function fn(a) {
return function(b) {
console.log(a + b);
}
}
var fn2 = fn(1);
fn2(5);
请编写一个函数add(3)(5) 让传入的参数相加
function add(a) {
return function(b) {
console.log(a + b);
}
}
add(3)(5);
简单的封装
function objFnc() {
var obj = {
name: 'zhangsan',
age: 20
}
return {
get: function() {
return obj;
},
set: function(name, val) {
obj[name] = val;
return obj;
}
};
}
var data = objFnc(); //* {get: ƒ, set: ƒ}
console.log("%c 🤷♀️: data.get() ", "font-size:16px;background-color:#fbf591;color:black;", data.get()) //8 {name: 'zhangsan', age: 20}
data.set('sex', 'man'); //* {name: 'zhangsan', age: 20, sex: 'man'}
console.log("%c 🤷♀️: data.get() ", "font-size:16px;background-color:#fbf591;color:black;", data.get()) //* {name: 'zhangsan', age: 20, sex: 'man'}
七、for循环中的闭包导致的错误,及其四种解决方案
详细见另一个文章for循环中的闭包导致的错误,及其四种解决方案,或手机直接扫码即可;