什么是闭包?
MDN官方话:
一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包(closure)。
也就是说,闭包让你可以在一个内层函数中访问到其外层函数的作用域。
在 JavaScript 中,每当创建一个函数,闭包就会在函数创建的同时被创建出来。
闭包作用之实现数据私有
全局变量,容易被随意修改,希望有些数据是私有的,不让外部随意的访问
例如
let money = 0
function fn() {
money++
console.log('打工挣钱,积蓄'+money +'元');
}
fn()
fn()
调用一次fn钱+1 ,结果有个小偷直接偷你1000块
let money = 0
function fn() {
money++
console.log('打工挣钱,积蓄'+money +'元');
}
fn()
fn()
//小偷
function thief() {
money - 1000
console.log('偷你1000块');
}
thief()
所以我们需要一个保险柜与一把钥匙对不对
原理:闭包让你可以在一个内层函数中访问到其外层函数的作用域
实现代码如下
function svaing() {
let money = 0
function fn() {
money++
console.log('打工挣钱,积蓄' + money + '元');
}
return fn
}
//钱放在存钱罐里
const key = svaing() //钥匙
key()
key()
//小偷
function thief() {
money - 1000
console.log('偷你1000块');
}
thief() //报错
现在这个小偷除非偷钥匙 不然是不是偷不了钱啦
这样便实现了数据的私有化
注意点:外部函数需要有对内部函数的引用也就是return (内存才不会被释放)
问题:由于内存不被释放,所以会造成内存泄漏,如何解决?
js垃圾回收机制:标记清除法
标记清除法基本概念:从全局触发,访问不到(无法触及)的内存空间,就会被自动回收
解决方案: 让return出来的函数赋予null
示例
function svaing() {
let money = 0
function fn() {
money++
console.log('打工挣钱,积蓄' + money + '元');
}
return fn
}
//钱放在存钱罐里
const key = svaing() //钥匙
key()
key()
fn = null //钥匙丢失 存钱罐被打破 内存释放
原理: 断开了之前对内部函数的引用,对应的缓存的内容便被释放
闭包私有场景应用
大家看一下如下代码
function Person() {
this.age='18'
let name='私有的'
this.getName = function () {
return name
}
this.setName = function (value) {
name=value
}
return this
}
const p = Person()
console.log(p.getName());
p.setName('我来了')
console.log(p.getName());
console.log(p.name)
console.log(p.age);
看结果
看到这个代码大家有没有想到什么 不买关子了 New操作符大家还记得不
我们用new操作符改造一下
function Person() {
this.age='18'
let name='私有的'
this.getName = function () {
return name
}
this.setName = function (value) {
name=value
}
}
//new操作符
//1:创建一个新对象
//2:让构造函数的this指向这个新对象
//3:执行构造函数
//4:返回实例
const p = new Person()
console.log(p.getName());
p.setName('我来了')
console.log(p.getName());
console.log(p.name)
console.log(p.age);
打印
可以说一模一样哈
所以大家可千万不要再说啥闭包是一个函数访问另一个函数内的变量了哈,现在年轻人面试这样的回答真让我尴尬