一篇文章帶你了解JavaScript 函數閉包
大家好,我是前端進階者。
JavaScript變量屬于 本地 或者 全局 范圍,使用閉包可以讓私有變量成為可能。
一、全局變量
一個函數可以訪問所有定義在函數 內部 的變量。
- function myFunction() {
- var a = 4;
- return a * a;
- }
但是函數也可以訪問定義在函數 之外 的變量。
- var a = 4; //全局變量
- function myFunction() {
- return a * a;
- }
第一個例子中,a是一個局部變量.。局部變量只能在定義的函數內使用。
全局變量可以被頁面(和窗口)中所有腳本使用(和更改),具有相同名稱的全局變量和局部變量是不同的變量。修改一個,不修改其他。
沒有關鍵字var創建的變量,總是全局的,即使是在函數中創建的。
二、變量的生命周期
全局變量只要應用程序(窗口/網頁)存在,它就存在。
局部變量生命周期較短。它們在函數被調用時被創建,當函數完成時被刪除。
三、為什么需要閉包?
假設要使用一個變量來計數某物,并且希望該計數器可用于所有函數??梢允褂靡粋€全局變量和一個增加計數器的函數。這個時候就需要閉包。
案例:一個計數器
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>項目</title>
- </head>
- <body style="background-color: aqua;">
- <p>使用全局變量計數</p>
- <button type="button" onclick="myFunction()">計數!</button>
- <p id="demo">0</p>
- <script>
- var counter = 0;
- function add() {
- return counter += 1;
- }
- function myFunction() {
- document.getElementById("demo").innerHTML = add();
- /* the counter is now equal to 3*/
- }
- </script>
- </body>
- </html>
注:
計數器只被add()函數改變。問題是,頁上的任何腳本可以改變計數器,無需調用add(),如果在函數中聲明計數器,沒有調用的時候,沒有人能改變它 add()。
- function add() {
- var counter = 0; //局部變量
- counter += 1;
- }
- add();
- add();
- add();
- // the counter should now be 3, but it does not work !
每次都要調用add()函數,計數器被設置為1。
四、JavaScript嵌套函數
所有函數都可以訪問全局作用域。
事實上,在JavaScript中,所有函數都能訪問它們外部的變量。JavaScript支持嵌套函數. 嵌套函數可以訪問它們 上面(外部) 的作用域。
實例中, 內部函數 plus() 在父函數中可以訪問 counter 變量。
- function add() {
- var counter = 0;
- function plus() {counter += 1;}
- plus();
- return counter;
- }
完整代碼:
- <!DOCTYPE html>
- <html>
- <title>項目</title>
- <body style="background-color: aqua;">
- <h2> JavaScript嵌套函數</h2>
- <p id="output"></p>
- <script>
- function outer() {
- var counter = 0;
- function inner() {
- counter++;
- }
- inner();
- return counter;
- }
- document.getElementById("output").innerHTML = `計數器是: ${outer()}`;
- </script>
- </body>
- </html>
如果能從外部調用plus()函數,這可能已經解決了計數器的困境,還需要找到一種方法來執行 counter = 0 只執行一次,需要閉包。
五、JavaScript 閉包
自調用函數
變量add被分配了自調用函數的返回值,自調用函數只運行一次. 它將counter設置為零(0),并返回函數表達式。
- var add = (function () {
- var counter = 0;
- return function () {return counter += 1;}
- })();
- add();
- add();
- add();
- // the counter is now 3
這樣 add 變成了一個函數. "精彩的" 部分是它可以在父作用域中訪問counter。
注:
這就是所謂的 JavaScript 閉包, 它使函數有“私有”變量成為可能。counter受匿名函數的作用域保護, 并且只能使用add函數修改。
六、總結
本文基于JavaScript基礎。從函數的基本概念,(變量和全局 )。函數為什么需要閉包,使用閉包可以讓私有變量成為可能。通過案例(計數器)的講解, 以及對嵌套函數中閉包的應用能夠更好的理解。
豐富的效果圖的展示,能夠幫助更好的去理解閉包這一概念。
希望能夠幫助你更好的學習JavaScript 。