前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JavaScript 学习-24.函数闭包(closure)

JavaScript 学习-24.函数闭包(closure)

作者头像
上海-悠悠
发布2022-05-25 11:41:50
3750
发布2022-05-25 11:41:50
举报
文章被收录于专栏:从零开始学自动化测试

前言

闭包是面试最喜欢问的一个问题了,面试官最喜欢问: 1.什么是闭包?2.闭包的作用是什么?

什么是闭包?

闭包(closure)是一种保护私有变量的机制,在函数执行时形成私有的作用域,保护里面的私有变量不受外界干扰,即形成一个不销毁的栈环境。

闭包的特性:

  • 函数嵌套函数
  • 内部函数可以访问外部函数的变量
  • 参数和变量不会被回收。

先看一个典型的闭包, 实现计数器的功能

代码语言:javascript
复制
function myCounter() {
   var counter = 0;

    function add() {
    counter += 1;
    console.log(counter);
    }
    return add;
}

var myAdd = myCounter();
myAdd();
myAdd();
myAdd();// 计数器现在为 3

在弄清楚闭包之前,我们需要弄明白一个概念:私有的作用域

变量作用域

var 声明的变量有2个作用域:全局作用域 和局部作用域。 let 和 const 声明的变量有3个作用域:全局作用域 和局部作用域, 还有个块作用域。块作用域这里就不讲了

全局作用域

在函数外部var 声明的变量就是全局作用域

代码语言:javascript
复制
var count = 0

// 每次调用fun() count 加1
function fun() {
    count += 1;
}

fun();
fun();
fun();
console.log(count);  // 3

函数局部作用域

在函数内部声明的变量是函数局部作用域

代码语言:javascript
复制
var count = 0

// 每次调用fun() count 加1
function fun() {
    var count = 0;
    count += 1;
}

fun();
fun();
fun();
console.log(count);  // 0

虽然函数内部也声明了一个count变量,但是跟函数外部的count其实是2个不同的变量,所以每次调用函数,仅仅只是内部变量count加1了,但是外部的count还是0。

计数器问题

如果我们想设置一个计数器,当我们打开一个页面,只有5次点击机会,点完就不能再点击了。

代码语言:javascript
复制
<body>
<button type="button" id="btn"></button>
<script>
var counter = 5;

// 每次调用fun() count -1
function fun() {
    counter -= 1;
    if (counter <= 0){
        document.getElementById('btn').disabled = true;
        return
    }

}

// 设置初始值
document.getElementById('btn').innerHTML = '还剩' + counter + '次';
// 每点一次减1
document.getElementById('btn').onclick = function () {
    fun();
    document.getElementById('btn').innerHTML = '还剩' + counter + '次';
}
</script>
</body>

实现效果

每点一次会减1

最后为0时不可被点击

看起来是没什么问题,但是这个会有一个安全隐患,由于counter变量是全局的,所以在其它任何地方都可以改变全局变量的值。 如果用户在控制台,改变了全局变量counter的值,比如我在console执行var counter=100

当我点一下按钮,就会变成99次

闭包的作用

为了解决这种全局变量导致的问题,所以我们需要在函数内部设置一个私有变量

代码语言:javascript
复制
<body>
<button type="button" id="btn"></button>
<script>
// 每次调用fun() count -1
function fun() {
    var counter = 5;
    document.getElementById('btn').innerHTML = '还剩' + counter + '次';
    function inner(){
        counter -= 1;
        if (counter <= 0){
            document.getElementById('btn').disabled = true;
        }
        return counter
    }
    return inner
}
mycounter = fun();
// 每点一次减1
document.getElementById('btn').onclick = function () {
    var x = mycounter();
    document.getElementById('btn').innerHTML = '还剩' + x + '次';
}
</script>
</body>

或者把counter作为一个变量传给函数,此时也不会影响

代码语言:javascript
复制
<body>
<button type="button" id="btn"></button>
<script>
// 每次调用fun() count -1
function fun(counter) {
    document.getElementById('btn').innerHTML = '还剩' + counter + '次';
    function inner(){
        counter -= 1;
        if (counter <= 0){
            document.getElementById('btn').disabled = true;
        }
        return counter
    }
    return inner
}

var counter = 5;
mycounter = fun(counter);

// 每点一次减1
document.getElementById('btn').onclick = function () {
    var x = mycounter();
    document.getElementById('btn').innerHTML = '还剩' + x + '次';
}
</script>
</body>

因为 fun()函数只执行一次,所以会锁定局部变量counter。

计数器

如果是从0开始,每运行一次函数加1,那么可以优化成以下代码

代码语言:javascript
复制
<body>
<button type="button" onclick="myFunction()">计数!</button>
<p id="demo"></p>
<script>
// 自调用函数
var add = (function () {
    var counter = 0;
    return function () {return counter += 1;}
})();

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

每点一次按钮会加1

闭包的作用

综上所述,闭包的作用就是在外部a函数执行后,闭包使得Javascript的垃圾回收机制不会收回a所占用的资源,因为a内部函数的变量要给到内部函数b继续使用。 那么闭包的好处有以下几点:

  • 保护函数内的变量安全
  • 在内存中维持一个变量(用的太多就变成了缺点,占内存) ;
  • 逻辑连续,当闭包作为另一个函数调用的参数时,避免你脱离当前逻辑而单独编写额外逻辑。
  • 方便调用上下文的局部变量。
  • 加强封装性,可以达到对变量的保护作用。

2022年第 11 期《python接口web自动化+测试开发》课程,6月5号开学!

2022年第 1 期《Python 测试平台开发》课程

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-05-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 从零开始学自动化测试 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 什么是闭包?
  • 变量作用域
    • 全局作用域
      • 函数局部作用域
      • 计数器问题
      • 闭包的作用
      • 计数器
      • 闭包的作用
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档