什么是js闭包,它能解决什么问题?

Javascript 496849654@qq.com 4年前 (2020-06-16) 840次浏览 0个评论

闭包是什么呢?
闭包是用来解决全局变量私有化的,也可以说成局部变量全局化。
那如果一个全局变量,我想让某个函数使用,别人不能使用,怎么办?

有人可能会说,那就声明成局部变量呗。局部变量每次调用的时候,都会重新声明赋值。而我是想让局部变量像全局变量一样,只声明赋值一次。

比如,我想做个计数器。点击一下加1。听起来很简单。代码如下:

<button type="button">计数</button>
<p id="demo">0</p>
<script>
var counter = 0;

function add(){
 document.getElementById("demo").innerHTML = ++counter;
}
</script>

上面的代码实现了想要的功能。但是,有一个安全隐患。变量counter除了函数add可以更改,其他任何代码都可以改变counter的值。

安全的做法是,只有函数add可以更改counter的值。就像有人提出的一样。把counter改成局部变量。那代码如下:

<button type="button">计数</button>
<p id="demo">0</p>
<script>
function add(){
 var counter = 0;
 document.getElementById("demo").innerHTML = ++counter;
}
</script>

这样的话,解决了counter不被别人修改的风险了,但是,我们的功能有问题了,点击输出的永远是1了。每次调用add,都重新声明了一个新变量counter并且赋值为0。

如果,var counter = 0;这一句只执行一次就好啦!
函数有一种调用方式叫自调用。自调用是只执行一次的。我们可以利用它来搞定。代码如下:

<button type="button">计数</button>
<p id="demo">0</p>
<script>
var add = (function () {
  var counter = 0;
  return function () {counter ++; return counter;}
})();
function doAdd(){
  document.getElementById("demo").innerHTML = add();
}
</script>

变量 add 的赋值是自调用函数的返回值。
这个自调用函数只运行一次。解决了刚刚执行多次的问题。它设置counter为零,并返回函数表达式。
add 成为了函数。它能够访问父作用域中的counter。

这叫做 JavaScript 闭包。它使函数拥有私有变量成为可能。

counter被这个匿名函数的作用域保护,并且只能使用 add 函数来修改。

闭包是一种保护私有变量的机制,在函数执行时形成私有的作用域,保护里面的私有变量不受外界干扰。

其实,还有一种办法可以解决全局变量安全的问题。之前我们介绍过块作用域,我们可以把开始的代码放到一个块里,就可以完美解决啦!代码如下:

<button type="button">计数</button>
<p id="demo">0</p>
<script>
{
  let counter = 0;

  function add(){
   document.getElementById("demo").innerHTML = ++counter;
  }
}
</script>

注意,块作用域声明变量用let。


css315 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:什么是js闭包,它能解决什么问题?
喜欢 (4)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到