通过一个简单的计数器案例理解JS中闭包概念

作者: liuwenhao 分类: 未分类 发布时间: 2020-10-14 10:36

首先我们来看一个基于传统JS实现的定时器案例:

let second = 0
function  counter(){
  second +=1
  return second
}
const recordSecond=setInterval(() => {
  if(second === 10){
    clearInterval(recordSecond)
    console.log('计时结束')
    return
  }
  console.log(`${counter()}秒`)
}, 1000);

在这个案例中,我们定义了一个counter函数进行计数,接着定义一个recordSecond定时器,每隔1s执行一次counter函数执行计数操作,当计数到10的时候,清除计数器。
这段代码很好理解,唯一需要注意的是,这里counter函数的执行是在console.log里面执行的,这个操作比较独特,在开发工作中可以借鉴。

接下来,我们看一下使用闭包实现的计数器:

function counter(){
  let second = 0
  function doCounter(){
    if(second  === 10 ){
      clearInterval(recordSecond)
      console.log('记录时间结束')
      return
    }
    second +=1
    console.log(`${second}秒`)
  }
  return doCounter
}
const doCounterFn=counter()

const recordSecond = setInterval(() => {
  doCounterFn()
}, 1000);

在这个案例中,我们定义了一个counter函数,在counter函数里面又定义了一个子函数doCounter,在doCounter中我们引用了外层函数的变量second,并在每次执行的时候将second变量+1。
这里内部的doCounter函数和外部的counter函数就形成了一个闭包,拥有只有自己作用域里面才能使用的second变量。

接下来,我们吧counter函数赋值给doCounterFn,我们看这段代码:

const doCounterFn=counter()

这段代码是什么意思呢?意思就是:执行counter函数,并将返回值赋值给doCounterFn,我们需要明确这一点:doCounterFn接受的是counter 返回的 doCounter子函数,doCounter子函数又拥有自己的作用域(即与counter构成的闭包)。
在接下来的代码中,我们通过定义定时器,执行doCounterFn函数,也就是执行了一个拥有自己独特作用域的doCounter函数,doCounter函数拿到外部的second变量,并对其执行+1操作,然后在下次执行的时候,doCounter拿到的变量是执行+1操作后的second变量,这看起来就像函数能够记住曾经使用过的变量。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注