[Day12] JavaScript - 闭包 Closure

闭包(Closure)在MDN的解释为: 是函式以及该函式被宣告时所在的作用域环境(lexical environment)的组合。

这样看起来好像有听没有懂,比较白话文的解释是:

  • 运作原理是呼叫 Function 内的 Function,内层 Function 作用域变数只会存在内层;
    内层 Function 变数可以不被释放、重复使用。
  • 闭包就是存取内部的函式,优点就是能把变数隐藏在里面让外部存取不到。

若不使用闭包的情况:

  • 假如我们想要做一个水果的计算程序,首先针对苹果做计算:

    var count = 0;
    function countApples() {
        count +=1;
        console.log(count + ' Apples');
    }
    
    countApples();   // 1 Apples
    countApples();   // 2 Apples
    countApples();   // 3 Apples
    
  • 接着继续写其他程序,写一写发现又需要计算橘子的数量,所以接着写:

    var count = 0;
    function countApples() {
        count +=1;
        console.log(count + ' Apples');
    }
    
    //其他程序...
    
    var count = 0;
    function countOranges() {
        count +=1;
        console.log(count + ' Oranges');
    }
    
    countApples();   // 1 Apples
    countApples();   // 2 Apples
    countApples();   // 3 Apples
    
    countOranges();   // 4 Orange  (我们要的结果是: 1 Orange)
    countOranges();   // 5 Orange  (我们要的结果是: 2 Orange)
    countOranges();   // 6 Orange  (我们要的结果是: 3 Orange)
    
    

    当我在最後执行这两个函式後发现,它把苹果跟橘子的数量全部都做累加了!!!

    原因是在这段程序里,我不小心把 count变成了 全域变数,让程序无法辨别现在是要针对苹果还是橘子做计算,而把它当成同一个count全部做加总。所以,这时我们就要使用闭包来解决这个问题了!

使用闭包:

  • 我们将刚刚的countApplescountOranges分别放入各自的函式appleFunc()orangeFunc()中,如此一来就可以避免count暴露在全域环境当中,count只有在appleFunc() 及 orangeFunc() 里面才可以被存取,在函式外是无法存取的。

  • 像这样在一个fucntion内包另一个function,并在外层函式 return 内层函式供最外层使用,通常就是使用到了闭包概念。

    function appleFunc(){
        var count = 0;
        function countApples() {          //是内部函式,是一个闭包
            count +=1;
            console.log(count + ' Apples');
        }
        return countApples
    }
    
    function orangeFunc() {
        var count = 0;
        function countOranges() {       //是内部函式,是一个闭包
            count +=1;
            console.log(count + ' Oranges');
        }
        return countOranges
    }
    
    
    var myAppleFunc = appleFunc();
    var myOrangeFunc = orangeFunc();
    
    myAppleFunc();    //1 Apples
    myOrangeFunc();   //1 Oranges
    
    myAppleFunc();    //2 Apples
    myAppleFunc();    //3 Apples
    myOrangeFunc();   //2 Oranges
    
    myOrangeFunc();   //3 Oranges
    myOrangeFunc();   //4 Oranges
    
    

  这样就成功的让myAppleFunc()myOrangeFunc()内的count分开计算,不互相干扰了。


/images/emoticon/emoticon07.gif

资料来源:
https://pjchender.blogspot.com/2017/05/javascript-closure.html
https://wcc723.github.io/javascript/2017/12/13/javascript-closure/


<<:  LeetCode解题 Day12

>>:  未来狂想:金融领域

Day13|【Git】档案管理 - 档案还原 git checkout

当我们不小心把档案或目录删除时,有什麽办法可以还原档案呢? git checkout 、git re...

TypeScript 能手养成之旅 Day 1 出发

TypeScript 能手养成之旅 Day 1 出发 前言 学习程序满一年了,转职成为工程师也有半年...

Day03-Nginx 简介

安装 Nginx $ sudo apt-get update $ sudo apt-get inst...

点光源与自发光

大家好,我是西瓜,你现在看到的是 2021 iThome 铁人赛『如何在网页中绘制 3D 场景?从 ...

Day 28【Deploy NFT - Deploy the Lazy Mint in Website】Vitalik Buterin mining Ethereum

// Thats proof of work 【前言】 今天终於来到这个 Project 测试的最...