js 一分钟学会使用闭包

前言

今天来谈谈闭包,不从晦涩难懂的文字来谈,直接用简单的代码,了解闭包到底大概是什么样子的,我们平时又怎么用到它。

函数作用域

了解闭包,我们首先要知道函数的作用域,它有一个特点,就是与调用时所在的作用域无关,只跟定义的所在的作用域有关,也就是从函数被写好时就固定了。

严格来讲,所有函数都是闭包。

但是因为我们平时写代码最多的状态,函数定义所在的作用域和函数调用时所在的作用域是一个作用域,所以闭包没什么讨论的意义。

下面是非常简单的例子,我们很容易得出,结果是out

let n = 'out'
// 函数定义时
let outFunc = () => {
    console.log(n)
}
// 函数调用时
outFunc() // out

假如我们嵌套了一个函数在内部,下面例子我们可以得到什么结论呢?

虽然我们的函数是在外部调用的,但是我们函数中输出结果变量n是内部函数定义时所在的变量作用域中的n

这就是闭包值得讨论的东西。

let n = 'out'
let outFunc = () => {
    let n = 'in'
    // 函数定义时
    return () => {
        console.log(n)
    }
}
// 函数调用时
outFunc()() // in

私有变量

我们知道了闭包的价值存在于函数中嵌套着另一个函数时,内部的函数可以访问外部函数内的局部变量,它有什么用呢?


我们先来看看这个例子,这个例子实现了函数执行对于某个变量的计数自增。

let count = 0
let add = () => {
    console.log(count++)
}

add() // 0
add() // 1
add() // 2

这段代码存在一个问题,就是count太容易被人修改了,这样的自增并不安全。


我们如何让count不会被人意外修改呢?让它成为私有变量。

我们就可以借用闭包的思想。

let add = (() => {
    let count = 0
    return () => {
        console.log(count++)
    }
})()

add() // 0
add() // 1
add() // 2

当外部的函数add在外部被定义出来的那一刻,内部函数所使用的局部变量count已经处于只有它可以访问的状态,属于它的私有变量


但是我们发现我们上面写的这种私有状态没办法复用,因为我们的add定义时就被调用,内部的私有状态只被一个闭包独享。

我们可以使用一个外部函数定义多个闭包,达到复用私有状态的目的:

let add = () => {
    let count = 0
    return () => {
        console.log(count++)
    }
}

let add1 = add()
let add2 = add()

add1() // 0
add1() // 1
add2() // 0
add2() // 1

还有局部的私有变量我们可以提升到入参位置,达到设置初始值的目的,除了定义时,后续也是不可修改的。

let add = (count) => {
    return () => {
        console.log(count++)
    }
}

let add1 = add(0)
let add2 = add(100)

add1() // 0
add1() // 1
add2() // 100
add2() // 101

综上,我们可以简单的做个总结,一个内部的函数被定义在一个外部的函数中,就可以将外部函数的变量作为自己的私有变量。

继续用一个例子加深理解,只要是内部的函数被定义时就可以了,即便这个函数是某个对象上的方法也可以。

let obj = {}

let addPrivateCount = (obj) => {
    let count = 0
    obj.getCount = () => {
        console.log(count++)
    }
}

addPrivateCount(obj)

obj.getCount() // 0
obj.getCount() // 1
obj.getCount() // 2

console.log(obj) // { getCount: [Function (anonymous)] }

我这里顺便输出了obj,告诉你上面只存在一个获取count的方法,但是并没有count变量,count可以算作它私有的变量,虽然可以获取,但是除了它的getCount方法访问,没有别的办法访问。

尾言

如果能够读懂这些小例子,相信闭包已经难不到你了,而且你也能够利用闭包去解决实际编程中的一些问题。

如果本文对你有帮助的话,欢迎点赞收藏,有什么意见或问题也欢迎提出,感谢~

你可能感兴趣的:(一分钟学习一个前端小知识,js,详解系列,javascript,前端,闭包)