偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

前端百題斬——用“閉包”問題征服面試官

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

[[403566]]

13.1 定義

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

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

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

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

13.3 流程

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

  1. function main() { 
  2.     const val1 = 20; 
  3.     var val2 = 2 
  4.     function valResult() { 
  5.         return val1 * val2; 
  6.     } 
  7.  
  8.     return valResult; 
  9.  
  10. var result = main(); 
  11. console.log(result()); // 40 

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

  1. 當(dāng)main函數(shù)執(zhí)行完畢后,main函數(shù)的執(zhí)行上下文從棧頂彈出;
  2. 返回的方法(valResult)中調(diào)用了main函數(shù)中的val1和val2變量,這兩個(gè)變量就會(huì)打包成closure閉包,加到[[scopes]];
  3. 調(diào)用返回的方法時(shí),作用域鏈為:result函數(shù)作用域——Closure(main)——全局作用域

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

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

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

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

缺點(diǎn)

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

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

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

  1. 如果閉包引入的函數(shù)是一個(gè)全局變量,那么閉包會(huì)一直存在直到頁面關(guān)閉;但如果這個(gè)閉包以后不再使用的話,就會(huì)造成內(nèi)存泄露;
  2. 如果引用閉包的函數(shù)是一個(gè)局部變量,等函數(shù)銷毀后,在下次JavaScript引擎執(zhí)行垃圾回收時(shí),判斷閉包內(nèi)容已經(jīng)不再被使用,則js引擎的垃圾回收器就會(huì)進(jìn)行回收。

13.5 用途

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

創(chuàng)建私有變量

  1. function MyName(name) { 
  2.     return { 
  3.         getName() { 
  4.             return name
  5.         } 
  6.     } 
  7.  
  8. const myName = MyName('lili'); 
  9. // 只能通過getName訪問對(duì)應(yīng)的名字,別的方式訪問不到 
  10. 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)聽器、Ajax請(qǐng)求。

  1. function fun(name) { 
  2.     setTimeout(() => { 
  3.         console.log(name); 
  4.     }, 1000); 
  5.  
  6. fun('linlin'); 

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

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

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

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

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

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

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

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

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

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

本文轉(zhuǎn)載自微信公眾號(hào)「執(zhí)鳶者」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系執(zhí)鳶者公眾號(hào)。

 

責(zé)任編輯:武曉燕 來源: 執(zhí)鳶者
相關(guān)推薦

2019-07-09 10:43:57

JavaScriptWeb前端

2025-03-18 12:00:00

閉包JavaScript前端

2021-10-19 22:23:05

typeof方式Instanceof

2021-05-09 22:00:59

TypeofInstanceof運(yùn)算符

2024-08-08 16:53:17

2018-04-13 14:53:13

PythonMySQL爬蟲

2021-05-30 19:02:59

變量對(duì)象上下文

2021-06-09 07:01:30

前端CallApply

2021-07-14 07:00:53

瀏覽器技巧前端

2021-10-18 09:01:01

前端賦值淺拷貝

2021-08-04 06:56:49

HTTP緩存前端

2021-05-12 07:04:55

Js變量方式

2021-11-19 09:01:09

防抖節(jié)流前端

2021-07-26 05:01:55

瀏覽器渲染流程

2021-06-28 07:12:28

賦值淺拷貝深拷貝

2021-04-13 19:05:06

Go閉包面試

2021-05-19 07:02:42

JS對(duì)象方法

2021-05-16 19:23:11

引用類型包裝

2021-06-07 07:01:43

js關(guān)鍵字運(yùn)行

2021-06-11 06:54:34

原型構(gòu)造函數(shù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)