闭包
当内部函数被保存到外部时,将会生成闭包。生成闭包后,内部函数依旧可以访问其所在的外部函数的变量。
闭包问题的解决方法:立即执行函数、let
详细解释:
当函数执行时,会创建一个称为执行期上下文的内部对象(AO),执行期上下文定义了一个函数执行时的环境。
函数还会获得它所在作用域的作用域链,是存储函数能够访问的所有执行期上下文对象的集合,即这个函数中能够访问到的东西都是沿着作用域链向上查找直到全局作用域。
函数每次执行时对应的执行期上下文都是独一无二的,当函数执行完毕,函数都会失去对这个作用域链的引用,JS 的垃圾回收机制是采用引用计数策略,如果一块内存不再被引用了那么这块内存就会被释放。
但是,当闭包存在时,即内部函数保留了对外部变量的引用时,这个作用域链就不会被销毁,此时内部函数依旧可以访问其所在的外部函数的变量,这就是闭包。
先看两个例子,两个例子都打印 5 个 5
for (var i = 0; i < 5; i++) {
setTimeout(function timer() {
console.log(i)
}, i * 100)
}
function test() {
var a = []
for (var i = 0; i < 5; i++) {
a[i] = function () {
console.log(i)
}
}
return a
}
var myArr = test()
for (var j = 0; j < 5; j++) {
myArr[j]()
}
解决方法: 使用立即执行函数
for (var i = 0; i < 5; i++) {
;(function (i) {
setTimeout(function timer() {
console.log(i)
}, i * 100)
})(i)
}
function test() {
var arr = []
for (i = 0; i < 10; i++) {
;(function (j) {
arr[j] = function () {
console.log(j)
}
})(i)
}
return arr
}
var myArr = test()
for (j = 0; j < 10; j++) {
myArr[j]()
}
闭包-封装私有变量
function Counter() {
let count = 0
this.plus = function () {
return ++count
}
this.minus = function () {
return --count
}
this.getCount = function () {
return count
}
}
const counter = new Counter()
counter.puls()
counter.puls()
console.log(counter.getCount())