閉包

閉包:從一函數(shù)外部訪問這一函數(shù)的內(nèi)部函數(shù),從而使這一函數(shù)內(nèi)部變量持續(xù)存在的實現(xiàn)

閉包的特性:

函數(shù)嵌套函數(shù)

內(nèi)部函數(shù)引起外部函數(shù)中變量的變化

參數(shù)和變量不會被垃圾回收機(jī)制回收

首先,先來觀察一個簡單的閉包

? ? function fn(){

? ? ? ? var a = 1;

? ? ? ? return function(){? //核心代碼1

? ? ? ? ? ? a++;

? ? ? ? ? ? console.log(a);

? ? ? ? }

? ? }

? ? var carry = fn();? //核心代碼2

? ? carry();? //2

? ? carry();? //3

1

2

3

4

5

6

7

8

9

10

核心代碼1:

fn 函數(shù)執(zhí)行完畢后把一個匿名函數(shù)當(dāng)作返回值返回出來。

核心代碼2:

var carry = fn(); 此行代碼將 fn() 傳遞給變量 carry . 無論是在 Java 還是JavaScript中把一個帶有返回值的方法傳遞給一個變量,那么傳遞的實質(zhì)便是此變量等同于方法的返回值,即 carry 等于返回的匿名函數(shù)

carry = function(){ a++; console.log(a); }

既然 carry 等同于匿名函數(shù),那么對于 carry 來說變量 a 即相當(dāng)于一個全局變量,為了方便理解可以這樣考慮:

在這里插入圖片描述

對于 js 來說函數(shù)是可以隨意嵌套的,那么全局變量也只是相對而言,就像上圖中對于內(nèi)涵函數(shù) carry 來說 a 變量就是一個全局變量,如果只執(zhí)行 carry 那么 a 就不會被重新定義,而是同全局變量一樣保存在內(nèi)存里。這樣就可以實現(xiàn)閉包。

閉包的其他實現(xiàn)方式

IIFE:Immediately Invoked Function Expression,意為立即調(diào)用函數(shù)表達(dá)式。

簡介:如果有些函數(shù)只使用一次,那么立即執(zhí)行就可以,連函數(shù)名都省掉,就是匿名函數(shù)

? ? <script>

? ? (function(){

? ? ? ? console.log("我是匿名函數(shù)");

? ? })();

? ? </script>

1

2

3

4

5

此方法不用被調(diào)用,立即執(zhí)行,并且只執(zhí)行一次。

在最開始的例子中我們發(fā)現(xiàn)外部函數(shù) fn 的變量定義只定義一次,閉包的核心只在返回函數(shù),那么為了節(jié)省全局變量可以將外部函數(shù)設(shè)為 IIFE 。

閉包實現(xiàn)中最重要的便是講內(nèi)部函數(shù)暴露在外面,下面講解一下用 IIFE 實現(xiàn),和暴露內(nèi)部函數(shù)的方法

暴露內(nèi)部函數(shù)的方法一:通過return返回內(nèi)部函數(shù)

? ? var fn = (function(){

? ? ? ? var a = 1;

? ? ? ? function add(){

? ? ? ? ? ? a++;

? ? ? ? }

? ? ? ? function print(){

? ? ? ? ? ? console.log(a);

? ? ? ? }

? ? ? ? return {add,print}

? ? })();

? ? var add = fn.add;

? ? var print = fn.print;

? ? add();

? ? print();? //2

1

2

3

4

5

6

7

8

9

10

11

12

13

14

暴露內(nèi)部函數(shù)的方法一:通過全局對象 window 將內(nèi)部函數(shù)暴露出來

? (function(){

? ? ? var a = 1;

? ? ? function add(){

? ? ? ? ? a++;

? ? ? }

? ? ? function print(){

? ? ? ? ? console.log(a);

? ? ? }

? ? ? window.fn={add,print}

? })();

? var add = fn.add;

? var print = fn.print;

? add();

? print();

1

2

3

4

5

6

7

8

9

10

11

12

13

14

文章最后發(fā)布于: 2019-11-16

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容