日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術(shù)文章
文章詳情頁

JavaScript閉包原理與用法學(xué)習(xí)筆記

瀏覽:190日期:2023-10-24 15:50:58

本文實例講述了JavaScript閉包原理與用法。分享給大家供大家參考,具體如下:

閉包(Closure)

閉包是一個函數(shù)和詞法環(huán)境的組合,函數(shù)聲明在這個詞法環(huán)境中。

詞法作用域:

看下面的一個例子:

function init() { var name = ’GaoPian’; // name是局部變量 function displayName() { //displayName();是內(nèi)部函數(shù),一個閉包 alert(name); // 使用外部函數(shù)聲明的變量 } displayName(); } init();

init()創(chuàng)建了一個局部變量name和一個函數(shù)displayName()。

函數(shù)displayName()是一個已經(jīng)定義在init()內(nèi)部的函數(shù),并且只能在函數(shù)init()里面才能訪問得到。

函數(shù)displayName()沒有自己的局部變量,但由于內(nèi)部函數(shù)可以訪問外部函數(shù)變量,displayName()可以訪問到聲明在外部函數(shù)init()的變量name,如果局部變量還存在的話,displayName()也可以訪問他們。

閉包

看下面一個例子

function makeFunc() { debugger var name = ’GaoPian’; function displayName() { alert(name); } return displayName; } var myFunc = makeFunc(); myFunc();

運行這段代碼和之前init()的方法的效果是一樣。

經(jīng)過debugger一遍之后發(fā)現(xiàn):

二者不同之處是,displayName()在執(zhí)行之前,這個內(nèi)部方法是從外部方法返回來的。   

首先,代碼還是會正確運行,在一些編程語言當(dāng)中,一個函數(shù)內(nèi)的局部變量只存在于該函數(shù)的執(zhí)行期間,隨后會被銷毀,一旦makeFunc()函數(shù)執(zhí)行完畢的話,變量名就不能夠被獲取,但是,由于代碼仍然正常執(zhí)行,這顯然在JS里是不會這樣的。這是因為函數(shù)在JS里是以閉包的形式出現(xiàn)的。

閉包是一個函數(shù)和詞法作環(huán)境的組合,詞法環(huán)境是函數(shù)被聲明的那個作用域,這個執(zhí)行環(huán)境包括了創(chuàng)建閉包時同一創(chuàng)建的任意變量,即創(chuàng)建的這個函數(shù)和這些變量處于同一個作用域當(dāng)中。在這個例子當(dāng)中,myFunc()是displayName()的函數(shù)實例,makeFunc創(chuàng)建的時候,displayName隨之也創(chuàng)建了。displayName的實例可以獲得詞法作用域的引用,在這個詞法作用域當(dāng)中,存在變量name,對于這一點,當(dāng)myFunc調(diào)用的話,變量name,仍然可以被調(diào)用,因此,變量’GaoPian’傳遞給了alert函數(shù)。

這里還有一個例子

function makeAdder(x) { return function (y) { return x + y; } } var add5 = makeAdder(5); var add10 = makeAdder(10); console.log(add5(2)); // 7 console.log(add10(2)); // 12

在這個例子當(dāng)中,我們定義了一個函數(shù)makeAdder(x),傳遞一個參數(shù)x,并且返回一個函數(shù),這個返回函數(shù)接收一個參數(shù)y,并返回x和y的和。   

實際上,makeAdder是一個工廠模式:它創(chuàng)建了一個函數(shù),這個函數(shù)可以計算特定值的和。在上面這個例子當(dāng)中,我們使用工廠模式來創(chuàng)建新的函數(shù), 一個與5進行加法運算——add5,一個與10進行加法運算——add10。add5和add10都是閉包,他們共享相同的函數(shù)定義,但卻存儲著不同的詞法環(huán)境,在add5的詞法環(huán)境當(dāng)中,x為5;在add10的詞法環(huán)境當(dāng)中,x變成了10。

閉包的實踐

閉包是很有用的,因為他讓我們把一些數(shù)據(jù)(詞法環(huán)境)和一些能夠獲取這些數(shù)據(jù)的函數(shù)聯(lián)系起來,這有點和面向?qū)ο缶幊填愃?,在面向?qū)ο缶幊坍?dāng)中,對象讓我們可以把一些數(shù)據(jù)(對象的屬性)和一個或多個方法聯(lián)系起來。

因此,你能夠像對象的方法一樣隨時使用閉包。實際上,大多數(shù)的前端JS代碼都是事件驅(qū)動性的:我們定義一些事件,當(dāng)這個事件被用戶所觸發(fā)的時候(例如用戶的點擊事件和鍵盤事件),我們的事件通常會帶上一個回調(diào):即事件觸發(fā)所執(zhí)行的函數(shù)。舉個栗子,假設(shè)我們希望在頁面上添加一些按鈕,這些按鈕能夠調(diào)整文字的大小,實現(xiàn)這個功能的方式是確定body的字體大小,然后再設(shè)置頁面上其他元素(例如標(biāo)題)的字體大小,我們使用em作為單位。

<style> body { font-family: Helvetica, Arial, sans-serif; font-size: 12px; } h1 { font-size: 1.5em; } h2 { font-size: 1.2em; } </style>

我們設(shè)置的調(diào)節(jié)字體大小的按鈕能夠改變body的font-size,并且這個調(diào)節(jié)能夠通過相對字體單位,反應(yīng)到其他元素上,

function makeSizer(size) { return function () { document.body.style.fontSize = size + ’px’; }; } var size12 = makeSizer(12); var size14 = makeSizer(14); var size16 = makeSizer(16);

size12,size14,size16是三個分別把字體大小調(diào)整為12,14,16的函數(shù),我們可以把他們綁定在按鈕上。

<button id='size-12'>12</button><button id='size-14'>14</button><button id='size-16'>16</button>

document.getElementById(’size-12’).onclick = size12; document.getElementById(’size-14’).onclick = size14; document.getElementById(’size-16’).onclick = size16;

通過閉包來封裝私有方法:類似JAVA語言能夠聲明私有方法,意味著只能夠在相同的類里面被調(diào)用,JS無法做到這一點,但卻可以通過閉包來封裝私有方法。私有方法不限制代碼:他們提供了管理命名空間的一種強有力方式。

下面代碼闡述了怎樣使用閉包來定義公有函數(shù),公有函數(shù)能夠訪問私有方法和屬性。

var counter = (function () { debugger; var privateCounter = 0; function changeBy(val) { privateCounter += val; } return { increment: function () {changeBy(1); }, decrement: function () {changeBy(-1); }, value: function () {return privateCounter; } }; })(); console.log(counter.value());// 0 counter.increment(); counter.increment(); console.log(counter.value());// 2 counter.decrement(); console.log(counter.value()); // 1

在之前的例子當(dāng)中,每個閉包具有他們自己的詞法環(huán)境,而在這個例子中,我們創(chuàng)建了一個單獨的詞法環(huán)境,這個詞法環(huán)境被3個函數(shù)所共享,這三個函數(shù)是counter.increment, counter.decrement和counter.value。

共享的詞法環(huán)境是由匿名函數(shù)創(chuàng)建的,一定義就可以被執(zhí)行,詞法環(huán)境包含兩項:變量privateCounter和函數(shù)changeBy,這些私有方法和屬性不能夠被外面訪問到,然而,他們能夠被返回的公共函數(shù)訪問到。這三個公有函數(shù)就是閉包,共享相同的環(huán)境,JS的詞法作用域的好處就是他們可以互相訪問變量privateCounter和changeBy函數(shù)。

下面一個例子:

var makeCounter = function () { var privateCounter = 0; function changeBy(val) { privateCounter += val; } return { increment: function () {changeBy(1); }, decrement: function () {changeBy(-1); }, value: function () {return privateCounter; } } }; var counter1 = makeCounter(); var counter2 = makeCounter(); alert(counter1.value()); /* Alerts 0 */ counter1.increment(); counter1.increment(); alert(counter1.value()); /* Alerts 2 */ counter1.decrement(); alert(counter1.value()); /* Alerts 1 */ alert(counter2.value()); /* Alerts 0 */

兩個計數(shù)器counter1和counter2分別是互相獨立的,每個閉包具有不同版本的privateCounter,每次計數(shù)器被調(diào)用,詞法環(huán)境會改變變量的值,但是一個閉包里變量值的改變并不影響另一個閉包里的變量。

循環(huán)中創(chuàng)建閉包:常見錯誤

看下面一個例子:

<p id='help'>Helpful notes will appear here</p><p>E-mail: <input type='text' name='email'></p><p>Name: <input type='text' name='name'></p><p>Age: <input type='text' name='age'></p>

function showHelp(help) { document.getElementById(’help’).innerHTML = help; } function setupHelp() { var helpText = [{’id’: ’email’, ’help’: ’Your e-mail address’}, {’id’: ’name’, ’help’: ’Your full name’}, {’id’: ’age’, ’help’: ’Your age (you must be over 16)’}]; for (var i = 0; i < helpText.length; i++) { var item = helpText[i]; document.getElementById(item.id).onfocus = function () {showHelp(item.help); } } } setupHelp();

helpText 數(shù)組定義了三個有用的hint,每個分別與輸入框的id相對應(yīng),每個方法與onfocus事件綁定起來。當(dāng)你運行這段代碼的時候,不會像預(yù)期的那樣工作,不管你聚焦在哪個輸入框,始終顯示你的age信息。

原因在于,分配給onfocus事件的函數(shù)是閉包,他們由函數(shù)定義構(gòu)成,從setupHelp函數(shù)的函數(shù)作用域獲取。三個閉包由循環(huán)所創(chuàng)建,每個閉包具有同一個詞法環(huán)境,環(huán)境中包含一個變量item.help,當(dāng)onfocus的回調(diào)執(zhí)行時,item.help的值也隨之確定,循環(huán)已經(jīng)執(zhí)行完畢,item對象已經(jīng)指向了helpText列表的最后一項。

解決這個問題的方法是使用更多的閉包,具體點就是提前使用一個封裝好的函數(shù):

function showHelp(help) { document.getElementById(’help’).innerHTML = help; } function makeHelpCallback(help) { return function () { showHelp(help); }; } function setupHelp() { var helpText = [{’id’: ’email’, ’help’: ’Your e-mail address’}, {’id’: ’name’, ’help’: ’Your full name’}, {’id’: ’age’, ’help’: ’Your age (you must be over 16)’}]; for (var i = 0; i < helpText.length; i++) { var item = helpText[i]; document.getElementById(item.id).onfocus = makeHelpCallback(item.help); } } setupHelp();

上面代碼運行正常,回調(diào)此時不共享一個詞法環(huán)境,makeHelpCallback函數(shù)給每個回調(diào)創(chuàng)造了一個詞法環(huán)境,詞法環(huán)境中的help指helpText數(shù)組中對應(yīng)的字符串,使用匿名閉包來重寫的例子如下:

function showHelp(help) { document.getElementById(’help’).innerHTML = help; } function setupHelp() { var helpText = [{’id’: ’email’, ’help’: ’Your e-mail address’}, {’id’: ’name’, ’help’: ’Your full name’}, {’id’: ’age’, ’help’: ’Your age (you must be over 16)’}]; for (var i = 0; i < helpText.length; i++) { (function () {var item = helpText[i];document.getElementById(item.id).onfocus = function () { showHelp(item.help);} })(); // Immediate event listener attachment with the current value of item (preserved until iteration). } } setupHelp();

如果不想使用閉包,也可以使用ES6的let關(guān)鍵字:

function showHelp(help) { document.getElementById(’help’).innerHTML = help; } function setupHelp() { var helpText = [{’id’: ’email’, ’help’: ’Your e-mail address’}, {’id’: ’name’, ’help’: ’Your full name’}, {’id’: ’age’, ’help’: ’Your age (you must be over 16)’}]; for (var i = 0; i < helpText.length; i++) { let item = helpText[i]; document.getElementById(item.id).onfocus = function () {showHelp(item.help); } } } setupHelp();

這個例子使用let代替var,所以,每個閉包綁定了塊級作用域,也就意味著不需要額外的閉包。

感興趣的朋友可以使用在線HTML/CSS/JavaScript代碼運行工具:http://tools.jb51.net/code/HtmlJsRun測試上述代碼運行效果。

更多關(guān)于JavaScript相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《javascript面向?qū)ο笕腴T教程》、《JavaScript錯誤與調(diào)試技巧總結(jié)》、《JavaScript數(shù)據(jù)結(jié)構(gòu)與算法技巧總結(jié)》、《JavaScript遍歷算法與技巧總結(jié)》及《JavaScript數(shù)學(xué)運算用法總結(jié)》

希望本文所述對大家JavaScript程序設(shè)計有所幫助。

標(biāo)簽: JavaScript
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
日本久久二区| 嫩草伊人久久精品少妇av杨幂| 国产精品一区二区三区四区在线观看 | 日韩综合在线| 国产一区二区三区四区五区 | 久久av国产紧身裤| 午夜亚洲福利| 视频精品一区| 欧美精品1区| 国产精品久久久久久久久妇女| 岛国av在线网站| 天堂网av成人| 首页国产欧美久久| 国产毛片精品| 日韩欧美一区二区三区在线观看| 免费av一区| 日韩av资源网| 久久久国产精品网站| 久久精品免费一区二区三区| 麻豆9191精品国产| 欧美激情久久久久久久久久久| 国产精品日本一区二区不卡视频| 国产成人精品三级高清久久91| 欧美日韩一二三四| 婷婷综合电影| 日韩高清中文字幕一区二区| 中文字幕一区二区三区四区久久 | 美女久久网站| 日韩精品高清不卡| 超级白嫩亚洲国产第一| 日韩精品一区第一页| 欧美激情福利| 视频一区二区三区中文字幕| 欧美黑人巨大videos精品| 亚洲激情偷拍| 成人台湾亚洲精品一区二区| 人人精品人人爱| 日韩在线看片| 国产精品夜夜夜| 国产精品免费看| 日本不卡免费高清视频在线| 日韩一区中文| 樱桃成人精品视频在线播放| 国产精品主播| 麻豆亚洲精品| 欧美理论视频| 日本高清不卡一区二区三区视频| 国产欧美日韩一级| 日韩午夜视频在线| 一区二区三区国产在线| 免费观看不卡av| 亚洲网站视频| 久久国产精品成人免费观看的软件| 日本欧美一区二区| 日本欧美在线看| 久久高清免费观看| 在线国产一区| 欧美资源在线| 亚洲欧美日本日韩| 欧美日韩国产欧| 99re国产精品| 中文字幕一区二区精品区| 日韩亚洲国产欧美| 中文在线不卡| 中文无码日韩欧| 亚洲精品麻豆| 日本一区二区三区视频在线看| 亚洲精品日本| 日本成人在线视频网站| 清纯唯美亚洲综合一区| 国产精品**亚洲精品| 欧美a一区二区| 97精品国产福利一区二区三区| 精品中文字幕一区二区三区| 国产精品色婷婷在线观看| 久久精品国产亚洲一区二区三区| 久久永久免费| 久久久久久久久丰满| 亚洲免费影院| 欧美视频久久| 黑人精品一区| se01亚洲视频 | 日本中文字幕一区二区视频 | 激情综合网站| 亚洲精品中文字幕99999| 91精品啪在线观看国产爱臀| 国产极品一区| 不卡av一区二区| 欧美在线不卡| 久久精品官网| 7777精品| 欧美+日本+国产+在线a∨观看| 一区二区精彩视频| 久久伊人国产| 亚洲成人日韩| 欧美啪啪一区| 一本一道久久a久久精品蜜桃| 日本久久二区| 国产韩日影视精品| 国产精品a级| 午夜精品网站| 桃色av一区二区| 91精品尤物| 日本欧美在线看| 日韩电影免费网站| 国产亚洲一区| 蘑菇福利视频一区播放| 四虎4545www国产精品| 日本视频在线一区| 石原莉奈在线亚洲二区| 欧美欧美黄在线二区| 丝袜亚洲精品中文字幕一区| 久久人人精品| 国产精品99久久精品| 国产精品啊啊啊| 日韩欧美中文字幕电影 | 日韩精品三区四区| 黄色成人91| 国产精品88久久久久久| 亚洲国产福利| 精品一区二区三区免费看| 婷婷成人av| 亚洲最新av| 亚洲欧美综合| 伊人久久大香线蕉av超碰演员| 久久中文字幕二区| 伊人精品一区| 亚州av乱码久久精品蜜桃| 香蕉精品视频在线观看| 亚洲精品1区2区| 久久午夜精品一区二区| 老司机精品久久| 日韩在线网址| 久久激情五月激情| 麻豆免费精品视频| 国产一区二区三区日韩精品| 国产一区二区三区久久| 中文字幕在线视频久| 久久久久久婷| 欧美日韩国产精品一区二区亚洲| 亚洲欧美日韩一区在线观看| 亚洲精品字幕| 国产精品三级| 亚洲性色av| 免费在线看一区| 国产精品久久777777毛茸茸| 色婷婷色综合| 免费人成网站在线观看欧美高清| 日本aⅴ精品一区二区三区| 欧美91在线|欧美| 欧美福利一区| 国产日产一区| 久久精品观看| 国产一区二区高清| 久久精品99国产精品日本| 在线中文字幕播放| 亚洲一二三区视频| 人在线成免费视频| 日本一不卡视频| 欧美日韩色图| 国产精品成人国产| 国产亚洲综合精品| 六月婷婷综合| 欧美亚洲三级| 精品1区2区3区4区| 荡女精品导航| 欧美日本精品| 另类国产ts人妖高潮视频| 国产精品极品在线观看| 日韩专区欧美专区| 日韩欧美二区| 久久久久久亚洲精品美女| 亚洲一区二区三区高清| 国产美女高潮在线观看| 国产精品嫩草影院在线看| 99在线|亚洲一区二区| 日韩在线视频精品| 麻豆91在线播放| 日本一区二区三区中文字幕| 日韩视频二区| 国内精品福利| 亚洲v在线看| 日韩精品91| 免费视频一区二区三区在线观看| 日本久久一区| 日本成人中文字幕在线视频| 中文一区在线| 国产视频一区免费看| 尤物精品在线| 成人国产精品久久| 国语精品一区| 97人人精品| 国产精品一区二区精品视频观看 | 日韩一区二区三区免费视频| 精品黄色一级片| 日本成人在线视频网站| 噜噜噜躁狠狠躁狠狠精品视频| 激情欧美一区二区三区| 欧美精品资源| 999精品色在线播放|