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