溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

JavaScript中“閉包”的含義和作用

發(fā)布時(shí)間:2021-06-16 09:15:44 來(lái)源:億速云 閱讀:154 作者:chen 欄目:web開(kāi)發(fā)

本篇內(nèi)容主要講解“JavaScript中“閉包”的含義和作用”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“JavaScript中“閉包”的含義和作用”吧!

JavaScript中“閉包”的含義和作用

13.1 定義

在JavaScript中,根據(jù)詞法作用域的規(guī)則,內(nèi)部函數(shù)總是可以訪(fǎng)問(wèn)其外部函數(shù)聲明的變量,當(dāng)通過(guò)調(diào)用一個(gè)外部函數(shù)返回一個(gè)內(nèi)部函數(shù)后,即使該外部函數(shù)已經(jīng)執(zhí)行結(jié)束了,但是內(nèi)部函數(shù)引用外部函數(shù)的變量依然保存在內(nèi)存中,就把這些變量的集合稱(chēng)為閉包。

13.2 閉包實(shí)現(xiàn)

在一個(gè)函數(shù)中嵌套另一個(gè)函數(shù)或者將一個(gè)匿名函數(shù)作為值傳入另一個(gè)函數(shù)中。

// 函數(shù)fun1中嵌套了fun2,fun2作為參數(shù)返回,外部調(diào)用時(shí)仍能打印val1,構(gòu)成閉包 function fun1() {     const val1 = 10;     function fun2() {         console.log(val1);     }      return fun2; }  function fun3() {     const val2 = 20;     // 定時(shí)器中的為一個(gè)匿名函數(shù),其作為參數(shù)傳入了,函數(shù)fun3執(zhí)行完畢之后,1s鐘后才會(huì)執(zhí)行定時(shí)器函數(shù),但此時(shí)還能打印val2,構(gòu)成閉包     setTimeout(function() {         console.log(val2);     }, 1000); }

13.3 流程

根據(jù)下面的函數(shù)來(lái)看看閉包的整個(gè)執(zhí)行流程

function main() {     const val1 = 20;     var val2 = 2     function valResult() {         return val1 * val2;     }      return valResult; }  var result = main(); console.log(result()); // 40

JavaScript中“閉包”的含義和作用

JavaScript中“閉包”的含義和作用

JavaScript中“閉包”的含義和作用

上圖中展示了各個(gè)時(shí)期的調(diào)用棧,需要重點(diǎn)關(guān)注以下幾點(diǎn):

  1. 鴻蒙官方戰(zhàn)略合作共建——HarmonyOS技術(shù)社區(qū)

  2. 當(dāng)main函數(shù)執(zhí)行完畢后,main函數(shù)的執(zhí)行上下文從棧頂彈出;

  3. 返回的方法(valResult)中調(diào)用了main函數(shù)中的val1和val2變量,這兩個(gè)變量就會(huì)打包成closure閉包,加到[[scopes]];

  4. 調(diào)用返回的方法時(shí),作用域鏈為:result函數(shù)作用域——Closure(main)——全局作用域

13.4 優(yōu)缺點(diǎn)

優(yōu)點(diǎn)

(1)可以重復(fù)使用變量,并且不會(huì)造成變量污染;

(2)可以用來(lái)定義私有屬性和私有方法

缺點(diǎn)

(1)會(huì)產(chǎn)生不銷(xiāo)毀的上下文,導(dǎo)致棧/堆內(nèi)存消耗過(guò)大

(2)會(huì)造成內(nèi)存泄露。

擴(kuò)展:閉包是怎么回收的?

  1. 鴻蒙官方戰(zhàn)略合作共建——HarmonyOS技術(shù)社區(qū)

  2. 如果閉包引入的函數(shù)是一個(gè)全局變量,那么閉包會(huì)一直存在直到頁(yè)面關(guān)閉;但如果這個(gè)閉包以后不再使用的話(huà),就會(huì)造成內(nèi)存泄露;

  3. 如果引用閉包的函數(shù)是一個(gè)局部變量,等函數(shù)銷(xiāo)毀后,在下次JavaScript引擎執(zhí)行垃圾回收時(shí),判斷閉包內(nèi)容已經(jīng)不再被使用,則js引擎的垃圾回收器就會(huì)進(jìn)行回收。

13.5 用途

閉包用途主要有以下兩個(gè):

創(chuàng)建私有變量

function MyName(name) {     return {         getName() {             return name;         }     } }  const myName = MyName('lili'); // 只能通過(guò)getName訪(fǎng)問(wèn)對(duì)應(yīng)的名字,別的方式訪(fǎng)問(wèn)不到 console.log(myName.getName()); // lili

作為回調(diào)函數(shù)。當(dāng)把函數(shù)作為值傳遞到某處,并在某個(gè)時(shí)刻進(jìn)行回調(diào)的時(shí)候就會(huì)創(chuàng)建一個(gè)閉包。例如定時(shí)器、DOM事件監(jiān)聽(tīng)器、Ajax請(qǐng)求。

function fun(name) {     setTimeout(() => {         console.log(name);     }, 1000); }  fun('linlin');

13.6 經(jīng)典閉包問(wèn)題

多個(gè)子函數(shù)的[[scope]]都是同時(shí)指向父級(jí),是完全共享的。因此當(dāng)父級(jí)的變量對(duì)象被修改時(shí),所有子函數(shù)都受到影響。

for (var i = 1; i < 5; i++) {     setTimeout(() => console.log(i), 1000); }

上述代碼本意是輸出1、2、3、4,但結(jié)果卻是四個(gè)5,為了解決該問(wèn)題,主要有三種辦法。

變量可以通過(guò) 函數(shù)參數(shù)的形式 傳入,避免使用默認(rèn)的[[scope]]向上查找

for (var i = 1; i < 5; i++) {     (function(i) {         setTimeout(() => console.log(i), 1000);     })(i); }

使用setTimeout包裹,通過(guò)第三個(gè)參數(shù)傳入。(注:setTimeout后面可以有多個(gè)參數(shù),從第三個(gè)參數(shù)開(kāi)始其就作為回掉函數(shù)的附加參數(shù))

for (var i = 1; i < 5; i++) {     setTimeout(value => console.log(value), 1000, i); }

使用 塊級(jí)作用域,讓變量成為自己上下文的屬性,避免共享

for (let i = 1; i < 5; i++) {     setTimeout(() => console.log(i), 1000); }

到此,相信大家對(duì)“JavaScript中“閉包”的含義和作用”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢(xún),關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI