闭包笔记自用

36 阅读2分钟

闭包的概念

闭包就是一个函数(姑且称为父函数)内的变量被这个函数内的另一个函数(子函数)所引用,所以在父函数执行完被弹出执行栈后,子函数内仍有一块空间保存了父函数作用域内的变量,这个空间称之为闭包。依靠闭包,我们可以完成变量的私有化。不正当的使用闭包会造成内存泄漏。

几个例子

function makeAdder(x) {
  return function(y) {
    return x + y
  }
}

var add5 = makeAdder(5)
var add10 = makeAdder(10)

console.log(add5(2))  // 7
console.log(add10(2)) // 12

add5 = null          // 释放对闭包的引用 
console.log(add5(1)) //Uncaught TypeError: add5 is not a function
function f1 () {
    var a = 10
    function f2 () {
        a++
        console.log(a)
    }
    return f2
}
var f = f1()
f()  // 11
f()  // 12
f()  // 13
-----------------------------------------------------------
function f3 () {
    var a = 10
    a++
    console.log(a)
}
// 每次调用这个函数都会重新在内存中创建变量,执行完之后就会销毁。
f3() // 11
f3() // 11
f3() // 11
-------------------------------------------------------------
function f1 () {
    var a = 10
    return function () {
        a++
        console.log(a)
    }
}
var a1 = f1()
var a2 = f1()

// a1,a2互不干扰
a1() // 11
a1() // 12
a1() // 13

a2() //11
a2() //12

a1() //14
var add = (function () { 
    var counter = 0; 
    return function () { 
        return counter += 1; 
    } 
})(); 

add(); 
add(); 
add(); // 3
for(var i = 0; i < 5; i++) {
    setTimeout(() => {
        console.log(i)
    }, i * 1000)
}

for(var i = 0; i < 5; i++) {
    (function(j){
        setTimeout(() => {
            console.log(j)
        }, j * 1000)
    })(i)
}

var data = []
for (var i = 0; i < 3; i++) {
  data[i] = function () {
    console.log(i)
  }
}
data[0]()
data[1]()
data[2]()
// 3 3 3

// 使用闭包
var data = []
for (var i = 0; i < 3; i++) {
  data[i] = (function (j) {
        return function () {
            console.log(j)
        }
  })(i)
}
data[0]()
data[1]()
data[2]()
// 0 1 2

// 使用let
var data = []
for (let i = 0; i < 3; i++) {
  data[i] = function () {
    console.log(i)
  }
}
data[0]()
data[1]()
data[2]()
// 0 1 2

闭包一定会造成内存泄漏吗?

不一定,如果没有引用外部函数的变量,那么外部函数的变量就会被回收,就不会造成内存泄漏。