最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

JavaScript 閉包

2020-04-11 17:25 作者:一枚猿  | 我要投稿

什么是JavaScript 閉包

函數(shù)和對(duì)其周圍狀態(tài)的引用捆綁在一起構(gòu)成閉包。也就是說(shuō),閉包可以讓你從內(nèi)部函數(shù)訪問(wèn)外部函數(shù)作用域。在 JavaScript 中,每當(dāng)函數(shù)被創(chuàng)建,就會(huì)在函數(shù)生成時(shí)生成閉包。


作用域

請(qǐng)看下面的代碼


function init(name){ ? ?// 內(nèi)部函數(shù),因此就形成了一個(gè)閉包 ? ?function show(name){ ? ? ? ?console.log('name',name); ? ?} ? ?show(name);}
init('愛上學(xué)院');


最后頁(yè)面效果如下:

init()?創(chuàng)建了一個(gè)局部變量?name?和一個(gè)名為?show()?的函數(shù)。show()?是定義在?init()?里的內(nèi)部函數(shù),并且僅在?init()?函數(shù)體內(nèi)可用。請(qǐng)注意,show()?沒(méi)有自己的局部變量。然而,因?yàn)樗梢栽L問(wèn)到外部函數(shù)的變量,所以?show()?可以使用父函數(shù)?init()?中聲明的變量?name?。

運(yùn)行該代碼后發(fā)現(xiàn),?show()?函數(shù)內(nèi)的?第4行語(yǔ)句成功執(zhí)行了。這個(gè)例子描述了分析器如何在函數(shù)嵌套的情況下解析變量名。詞法一詞指的是,詞法作用域根據(jù)源代碼中聲明變量的位置來(lái)確定該變量在何處可用。嵌套函數(shù)可訪問(wèn)聲明于它們外部作用域的變量。


下面我們來(lái)看第二個(gè)例子:

function sum(x) { ? ?return function sum1(y) { ? ? ? ?return x + y; ? ?}}
document.write(sum(2)(5));

執(zhí)行上面代碼,最后會(huì)在頁(yè)面顯示“7”,如下圖:


實(shí)用的閉包

閉包很有用,因?yàn)樗试S將函數(shù)與其所操作的某些數(shù)據(jù)(環(huán)境)關(guān)聯(lián)起來(lái)。這顯然類似于面向?qū)ο缶幊獭T诿嫦驅(qū)ο缶幊讨?,?duì)象允許我們將某些數(shù)據(jù)(對(duì)象的屬性)與一個(gè)或者多個(gè)方法相關(guān)聯(lián)。

因此,通常你使用只有一個(gè)方法的對(duì)象的地方,都可以使用閉包。

在 Web 中,你想要這樣做的情況特別常見。大部分我們所寫的?JavaScript 代碼都是基于事件的 — 定義某種行為,然后將其添加到用戶觸發(fā)的事件之上(比如點(diǎn)擊或者按鍵)。我們的代碼通常作為回調(diào):為響應(yīng)事件而執(zhí)行的函數(shù)。


我們來(lái)看下面一個(gè)例子:點(diǎn)擊按鈕改變文字的字體大小。代碼(只展示js代碼)和頁(yè)面效果如下:

上面的代碼,是我們通常的寫法。下面我們就采用閉包的形式來(lái)寫。

采用閉包形式改寫的代碼如下:

function changeFontSize(fontSize) { ? ?return function () { ? ? ? ?document.getElementById("msg").style.fontSize = `${fontSize}px`; ? ?}}const changeFontSize18 = changeFontSize(18);const changeFontSize24 = changeFontSize(24);const changeFontSize32 = changeFontSize(32);document.getElementById("btn18").onclick = changeFontSize18;document.getElementById("btn24").onclick = changeFontSize24;document.getElementById("btn32").onclick = changeFontSize32;


私有方法

編程語(yǔ)言中,比如 Java,是支持將方法聲明為私有的,即它們只能被同一個(gè)類中的其它方法所調(diào)用。

而 JavaScript 沒(méi)有這種原生支持,但我們可以使用閉包來(lái)模擬私有方法。私有方法不僅僅有利于限制對(duì)代碼的訪問(wèn):還提供了管理全局命名空間的強(qiáng)大能力,避免非核心的方法弄亂了代碼的公共接口部分。


下面的示例展現(xiàn)了如何使用閉包來(lái)定義公共函數(shù),并令其可以訪問(wèn)私有函數(shù)和變量。這個(gè)方式也稱為模塊模式

const Count = (function () { ? ?// 定一個(gè)變量 ? ?let count = 0;
? ?// 定一個(gè)調(diào)整count的方法,該方法只能在這里使用 ? ?function change(val) { ? ? ? ?count += val; ? ?}
? ?return { ? ? ? ?add: function (step) { ? ? ? ? ? ?change(step); ? ? ? ?}, ? ? ? ?get: function () { ? ? ? ? ? ?return count; ? ? ? ?} ? ?}})();// 獲取count的值console.log(Count.get());// 0// count增加1Count.add(1)// count增加20Count.add(20)// 獲取count的值console.log(Count.get());// 21// count值減小3Count.add(-3)// 獲取count的值console.log(Count.get());// 18


在之前的示例中,每個(gè)閉包都有它自己的語(yǔ)法環(huán)境;而這次我們只創(chuàng)建了一個(gè)語(yǔ)法環(huán)境,為兩個(gè)函數(shù)所共享:Count.add和?Count.get。

該共享環(huán)境創(chuàng)建于一個(gè)立即執(zhí)行的匿名函數(shù)體內(nèi)。這個(gè)環(huán)境中包含兩個(gè)私有項(xiàng):名為?count?的變量和名為?change?的函數(shù)。這兩項(xiàng)都無(wú)法在這個(gè)匿名函數(shù)外部直接訪問(wèn)。必須通過(guò)匿名函數(shù)返回的兩個(gè)公共函數(shù)訪問(wèn)。

這兩個(gè)公共函數(shù)是共享同一個(gè)環(huán)境的閉包。多虧 JavaScript 的語(yǔ)法作用域,它們都可以訪問(wèn)?count?變量和?change?函數(shù)。


下面我們來(lái)把上面的代碼做一下微調(diào):創(chuàng)建兩個(gè)Count。


const Count = function () { ? ?// 定一個(gè)變量 ? ?let count = 0;
? ?// 定一個(gè)調(diào)整count的方法,該方法只能在這里使用 ? ?function change(val) { ? ? ? ?count += val; ? ?}
? ?return { ? ? ? ?add: function (step) { ? ? ? ? ? ?change(step); ? ? ? ?}, ? ? ? ?get: function () { ? ? ? ? ? ?return count; ? ? ? ?} ? ?}};const Count1 = Count();const Count2 = Count();
// 獲取Count1里面的count值console.log("Count1里面的count:", Count1.get());// 獲取Count2里面的count值console.log("Count2里面的count:", Count2.get());// Count1里面的count增加1Count1.add(1)console.log("==========Count1里面的count增加1================");// 獲取Count1里面的count值console.log("Count1里面的count:", Count1.get());// 獲取Count2里面的count值console.log("Count2里面的count:", Count2.get());// Count2里面的count增加1Count2.add(13)console.log("==========Count2里面的count增加13================");// 獲取Count1里面的count值console.log("Count1里面的count:", Count1.get());// 獲取Count2里面的count值console.log("Count2里面的count:", Count2.get());


運(yùn)行結(jié)果如下:


我們會(huì)發(fā)現(xiàn)兩個(gè)計(jì)數(shù)器?Count1?和?Count2?,每個(gè)閉包都是引用自己詞法作用域內(nèi)的變量?count?。

每次調(diào)用其中一個(gè)計(jì)數(shù)器時(shí),通過(guò)改變這個(gè)變量的值,會(huì)改變這個(gè)閉包的詞法環(huán)境。然而在一個(gè)閉包內(nèi)對(duì)變量的修改,不會(huì)影響到另外一個(gè)閉包中的變量。






JavaScript 閉包的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
马边| 新蔡县| 红河县| 齐齐哈尔市| 芦山县| 文昌市| 金溪县| 余江县| 长岭县| 汉沽区| 昂仁县| 土默特右旗| 遂宁市| 莱芜市| 苏尼特右旗| 崇文区| 甘谷县| 汤阴县| 敖汉旗| 剑川县| 垦利县| 西城区| 镇平县| 珲春市| 奎屯市| 巴东县| 木里| 大兴区| 如皋市| 香格里拉县| 定安县| 萝北县| 噶尔县| 晴隆县| 保德县| 社旗县| 仁怀市| 女性| 闵行区| 通山县| 罗江县|