成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

死磕JS:閉包到底是個什么鬼?

開發(fā) 前端
在JavaScript這門語言中,閉包是它的核心基礎(chǔ)之一,可以說是一個特色了,但是很多從事前端工作的程序員并沒有真正的理解它!

[[385641]]

本文轉(zhuǎn)載自微信公眾號「前端思維框架」,作者ViktorHub。轉(zhuǎn)載本文請聯(lián)系前端思維框架公眾號。     

 在JavaScript這門語言中,閉包是它的核心基礎(chǔ)之一,可以說是一個特色了,但是很多從事前端工作的程序員并沒有真正的理解它!

閉包有多重要?如果你是初入前端的朋友,我可以肯定得告訴你,前端面試,必問閉包。面試官們常常用對閉包的了解程度來判定面試者的基礎(chǔ)水平,保守估計,10個前端面試者,至少5個都死在閉包上。

通過本文講解,希望你可以重新認(rèn)識一下閉包!

函數(shù)調(diào)用時發(fā)生了什么?

為了理解閉包,首先我們需要完全理解 JavaScript 到底是如何工作的!

那么函數(shù)調(diào)用是會發(fā)生什么呢?

當(dāng)瀏覽器在解析 JS代碼的時候,會進(jìn)行一個預(yù)解析的操作,會有一個js解析器,里面會執(zhí)行其中的兩步操作:

1、預(yù)解析,找一些東西(var function 參數(shù));

2、逐行去解讀代碼。

當(dāng)解析器解讀函數(shù)調(diào)用時,會將整個函數(shù)執(zhí)行一個入棧操作,并為函數(shù)創(chuàng)建一個新的執(zhí)行上下文。函數(shù)內(nèi)部可以看作是一個小的區(qū)域,它有它自己的作用域和執(zhí)行線程,也要逐行解讀。當(dāng)函數(shù)顯式返回(到達(dá)return語句)或隱式返回(默認(rèn)情況下函數(shù)返回undefined)時,函數(shù)將出棧,其執(zhí)行上下文也將被銷毀。

閉包是什么鬼?

我們先來看下這段代碼:

  1. let name = "John" 
  2.  
  3. function greet() { 
  4.   const greeting = "Hi" 
  5.  
  6.   function printHi() { 
  7.     console.log(greeting + ' ' + name
  8.   } 
  9.   printHi() 
  10.  
  11. name = "Jane" 
  12.  
  13. greet() // "Hi Jane" 

我們發(fā)現(xiàn),子函數(shù) printHi 可以訪問全局作用域和其父函數(shù) greet 的局部作用域。

注意,我們實(shí)際上可以訪問函數(shù)執(zhí)行期間可用的“新”數(shù)據(jù),而不是聲明。這就是詞法作用域在 JavaScript 中的工作方式。

但是如果我們返回一個函數(shù),而不是僅僅在外部函數(shù)體中調(diào)用它,會發(fā)生什么呢?

看好了,奇跡出現(xiàn)了!

從一個函數(shù)中返回的函數(shù)不僅僅是一個簡單的函數(shù)定義,它是這個定義加上它可以訪問并需要執(zhí)行的變量,這些變量存儲在它附帶的詞法作用域中。

我們剛剛描述的就是閉包。從形式上講,閉包是一個「即使在詞法范圍之外調(diào)用,仍可以記住它的詞法范圍」的函數(shù)。

  1. function creator(num) { 
  2.   return function() { 
  3.     num = num * 2 
  4.     console.log(num) 
  5.   } 
  6.  
  7. const double = creator(5) 
  8. double() //10 
  9. double() //20 
  10.  
  11. const double2 = creator(7) 
  12. double2() // 14 
  13. double2() //28 
  14.  
  15. double() // 40 

正如我們在上面的代碼片段中看到的,每當(dāng)我們調(diào)用 double 時,它都會更新存儲在其詞法作用域中的同一個變量(來自其父函數(shù)的num),從技術(shù)上講,這是函數(shù)所具有的隱藏 [[scope]] 屬性。

如果你想知道閉包到底有什么用,請繼續(xù)看下面的示例。

模塊封裝

閉包允許我們保護(hù)或隱藏某些信息。[[scope]] 是一個隱藏的屬性,所以我們不能像使用標(biāo)準(zhǔn)對象那樣訪問和更新它。還有一點(diǎn)很重要,我們可以返回一組存儲在對象上的函數(shù),它們都是閉包。

在下面的代碼片段中,我們利用了所謂的IIFE(立即執(zhí)行函數(shù)),它允許我們消除調(diào)用外部函數(shù)的中間步驟,就像我們在賦值時直接調(diào)用它一樣。

  1. const myModule  = (function(){ 
  2.   const apiKey = "123456789" 
  3.  
  4.   return { 
  5.     displayKey() { 
  6.       console.log(apiKey) 
  7.     } 
  8.   }  
  9. })() 
  10.  
  11. myModule.displayKey() // "123456789" 

如果我們將這個模塊 export 出去, 提供給其他人使用,我們?yōu)樗麥?zhǔn)備的 API 不允許他更改 apiKey,這就做到了只讀屬性,除了在源代碼中重寫它之外,調(diào)用方不可能更改它。

緩存和記憶化

假設(shè)您想創(chuàng)建一個簡單的ID生成器。為了確??偸欠祷乇壬弦粋€高的數(shù)字,也可以使用閉包。我們將緩存當(dāng)前變量中最高的 ID 值。

  1. const newID = (function() { 
  2.   let current = 0 
  3.   return function() { 
  4.     return ++current 
  5.   } 
  6. })() 
  7.  
  8. newID() // 1 
  9. newID() // 2 

當(dāng)我們的算法時間復(fù)雜度很高時,這種緩存方式就非常有用,我們可以將部分結(jié)果存儲在緩存中,當(dāng)我們使用更高的數(shù)字進(jìn)行計算時,我們可以使用緩存中的數(shù)據(jù)作為基礎(chǔ)。這個過程叫做記憶化。一個最好的例子就是處理處理遞歸問題,比如斐波那契序列。

  1. const factorialMemo = (function() { 
  2.   const cache = {} 
  3.   return function factorial(n) { 
  4.     if(n === 1 || n === 0) { 
  5.       return 1 
  6.     } else if (cache[n]) { 
  7.       return cache[n] 
  8.     } else { 
  9.       cache[n] = n * factorial(n-1) 
  10.       return cache[n] 
  11.     } 
  12.   } 
  13. })() 
  14.  
  15.  
  16. factorialMemo(5) //120 
  17. // cache object looks like {'2': 2, '3' : 6, '4' : 24, '5' : 120} 
  18. factorialMemo(6) // 6 * cached 120  

好了,今天的內(nèi)容到此就結(jié)束了,你有 get 到閉包到底是個什么鬼了嗎?當(dāng)然要熟練掌握,還需要你在不斷的練習(xí)與總結(jié)中自我體會!

在《面向?qū)ο蠓治雠c設(shè)計》這本書里有一句話對閉包的概括我很喜歡,他是這樣說的:

“閉包是懶人的對象,對象是天然的閉包!”

慢慢悟吧,歡迎評論交流,周末愉快~

 

責(zé)任編輯:武曉燕 來源: 前端思維框架
相關(guān)推薦

2020-10-25 20:05:29

Pythonyield開發(fā)

2022-02-16 20:04:08

容器KubernetesShim

2020-09-27 06:53:57

MavenCDNwrapper

2022-11-02 15:00:03

Java值傳遞引用傳遞

2019-10-30 10:13:15

區(qū)塊鏈技術(shù)支付寶

2024-09-11 13:58:18

2022-02-22 13:20:57

RSA算法加密

2021-01-29 12:24:22

電腦電子計算機(jī)

2012-02-13 15:50:59

2021-06-03 08:32:18

JVM調(diào)優(yōu)虛擬機(jī)

2021-02-18 07:43:25

TCP協(xié)議網(wǎng)絡(luò)

2012-12-27 11:11:54

華為任正非

2018-09-06 11:20:24

CDNDDoS網(wǎng)站

2016-10-21 09:58:19

WindowsKMSOEM系統(tǒng)

2015-05-21 15:45:13

2022-01-10 11:16:40

漏洞 Log4j2Jndi

2022-09-02 17:26:18

Golang閉包

2010-06-28 15:58:45

EclipseJavaIDE

2010-06-29 13:39:26

Eclipse什么玩意兒

2010-07-02 10:10:09

Eclipse
點(diǎn)贊
收藏

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

主站蜘蛛池模板: 国产精品免费观看 | 亚洲 欧美 综合 | 色呦呦在线 | 麻豆一区二区三区 | a免费观看| 日本免费一区二区三区 | h视频免费在线观看 | 日韩成人 | 另类二区| 久久国产精品99久久久久 | 日日操视频 | 国产日韩欧美精品一区二区 | 国产精品久久久久久婷婷天堂 | 亚洲精品久久久久久国产精华液 | 久久久91精品国产一区二区三区 | 国产精品大片在线观看 | 免费黄色片在线观看 | 一级毛片视频在线 | 亚洲成人av | 黄色日本视频 | 久亚州在线播放 | 拍真实国产伦偷精品 | 99在线免费视频 | 久久精品免费一区二区三 | 亚洲久久一区 | 成人h视频在线 | 欧美激情视频一区二区三区在线播放 | 欧美一区二区三区视频 | av天天澡天天爽天天av | 99精品国产一区二区三区 | 色视频网站 | 日韩电影免费观看中文字幕 | 精品一区av | 久久亚洲一区二区三区四区 | 日干夜操| 日韩a在线 | 国产精品久久久久久亚洲调教 | 久久久久国产精品 | 免费观看一级特黄欧美大片 | 人人种亚洲 | h视频免费在线观看 |