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

Web前端:征服 JavaScript 面試之什么是閉包?

開發 前端
在我面試時問出的一系列問題里,閉包通常是我問的第一個或最后一個問題。坦白地說,如果你連閉包也弄不明白,你是不會在 JavaScript 的道路上走多遠的。

 前言

在我面試時問出的一系列問題里,閉包通常是我問的***個或***一個問題。坦白地說,如果你連閉包也弄不明白,你是不會在 JavaScript 的道路上走多遠的。

你別東張西望,說的就是你。你真的理解如何構建一個嚴謹的 JavaScript 應用?你真的理解代碼背后發生的事情或者說一個應用程序是如何工作的?我表示懷疑。如果連個閉包問題都搞不清的話,真是有點夠嗆。

[[270040]]

你不僅僅應該了解閉包的機制,更應該了解閉包為什么很重要,以及能夠很容易地回答出閉包的幾種可能的應用場景。

閉包在 JavaScript 中常用來實現對象數據的私有,在事件處理和回調函數中也常常會用到它,此外還有偏函數應用(partial applications)和柯里化(currying),以及其他函數式編程模式。

我不在乎面試者是否知道“closure”這個單詞或者它的專業定義。我只想弄清他們是否理解基本原理。如果他們沒有,那么通常意味著這些面試者在構建實際 JavaScript 應用方面并沒有很多經驗。

如果你不能回答這個問題,你只是個初級開發者。不管你實際上已經干這個多久了。

為了快速理解下面的內容:你想一下能否舉出兩個閉包的通用場景?

什么是閉包?

簡言之,閉包是由函數引用其周邊狀態(詞法環境)綁在一起形成的(封裝)組合結構。在 JavaScript 中,閉包在每個函數被創建時形成。

這是基本原理,但為什么我們關心這些?實際上,由于閉包與它的詞法環境綁在一起,因此閉包讓我們能夠從一個函數內部訪問其外部函數的作用域。

要使用閉包,只需要簡單地將一個函數定義在另一個函數內部,并將它暴露出來。要暴露一個函數,可以將它返回或者傳給其他函數。

內部函數將能夠訪問到外部函數作用域中的變量,即使外部函數已經執行完畢。

閉包使用的例子

閉包的用途之一是實現對象的私有數據。數據私有是讓我們能夠面向接口編程而不是面向實現編程的基礎。而面向接口編程是一個重要的概念,有助于我們創建更加健壯的軟件,因為實現細節比接口約定相對來說更加容易被改變。

“面向接口編程,別面向實現編程。” 設計模式:可復用面向對象軟件的要素

在 JavaScript 中,閉包是用來實現數據私有的原生機制。當你使用閉包來實現數據私有時,被封裝的變量只能在閉包容器函數作用域中使用。你無法繞過對象被授權的方法在外部訪問這些數據。在 JavaScript 中,任何定義在閉包作用域下的公開方法才可以訪問這些數據。例如:

  1. const getSecret = (secret) => { 
  2.  return { 
  3.  get: () => secret 
  4.  }; 
  5. }; 
  6. test('Closure for object privacy.', assert => { 
  7.  const msg = '.get() should have access to the closure.'
  8.  const expected = 1; 
  9.  const obj = getSecret(1); 
  10.  const actual = obj.get(); 
  11.  try { 
  12.  assert.ok(secret, 'This throws an error.'); 
  13.  } catch (e) { 
  14.  assert.ok(true, `The secret var is only available 
  15.  to privileged methods.`); 
  16.  } 
  17.  assert.equal(actual, expected, msg); 
  18.  assert.end(); 
  19. }); 

在上面的例子里,get() 方法定義在 getSecret() 作用域下,這讓它可以訪問任何 getSecret()中的變量,于是它就是一個被授權的方法。在這個例子里,它可以訪問參數 secret。

對象不是唯一的產生私有數據的方式。閉包還可以被用來創建有狀態的函數,這些函數的執行過程可能由它們自身的內部狀態所決定。例如:

  1. const secret = (msg) => () => msg; 
  2. // Secret - creates closures with secret messages. 
  3. // https://gist.github.com/ericelliott/f6a87bc41de31562d0f9 
  4. // https://jsbin.com/hitusu/edit?html,js,output 
  5. // secret(msg: String) => getSecret() => msg: String 
  6. const secret = (msg) => () => msg; 
  7. test('secret', assert => { 
  8.  const msg = 'secret() should return a function that returns the passed secret.'
  9.  const theSecret = 'Closures are easy.'
  10.  const mySecret = secret(theSecret); 
  11.  const actual = mySecret(); 
  12.  const expected = theSecret; 
  13.  assert.equal(actual, expected, msg); 
  14.  assert.end(); 
  15. }); 

在函數式編程中,閉包經常用于偏函數應用和柯里化。為了說明這個,我們先定義一些概念:

函數應用:一個過程,指將參數傳給一個函數,并獲得它的返回值。

偏函數應用:一個過程,它傳給某個函數其中一部分參數,然后返回一個新的函數,該函數等待接受后續參數。換句話說,偏函數應用是一個函數,它接受另一個函數為參數,這個作為參數的函數本身接受多個參數,它返回一個函數,這個函數與它的參數函數相比,接受更少的參數。偏函數應用提前賦予一部分參數,而返回的函數則等待調用時傳入剩余的參數。

偏函數應用通過閉包作用域來提前賦予參數。你可以實現一個通用的函數來賦予指定的函數部分參數,它看起來如下:

  1. partialApply(targetFunction: Function, ...fixedArgs: Any[]) => 
  2.  functionWithFewerParams(...remainingArgs: Any[]) 

如果你要更進一步理解上面的形式,你可以看這里。

partialApply 接受一個多參數的函數,以及一串我們想要提前賦給這個函數的參數,它返回一個新的函數,這個函數將接受剩余的參數。

下面給一個例子來說明,假設你有一個函數,求兩個數的和:

  1. const add = (a, b) => a + b; 

現在你想要得到一個函數,它能夠對任何傳給它的參數都加 10,我們可以將它命名為 add10()。add10(5) 的結果應該是 15。我們的 partialApply() 函數可以做到這個:

  1. const add10 = partialApply(add, 10); 
  2. add10(5); 

在這個例子里,參數 10 通過閉包作用域被提前賦予 add(),從而讓我們獲得 add10()。

現在讓我們看一下如何實現 partialApply():

  1. // Generic Partial Application Function 
  2. // https://jsbin.com/biyupu/edit?html,js,output 
  3. // https://gist.github.com/ericelliott/f0a8fd662111ea2f569e 
  4. // partialApply(targetFunction: Function, ...fixedArgs: Any[]) => 
  5. // functionWithFewerParams(...remainingArgs: Any[]) 
  6. const partialApply = (fn, ...fixedArgs) => { 
  7.  return function (...remainingArgs) { 
  8.  return fn.apply(this, fixedArgs.concat(remainingArgs)); 
  9.  }; 
  10. }; 
  11. test('add10', assert => { 
  12.  const msg = 'partialApply() should partially apply functions' 
  13.  const add = (a, b) => a + b; 
  14.  const add10 = partialApply(add, 10); 
  15.  const actual = add10(5); 
  16.  const expected = 15; 
  17.  assert.equal(actual, expected, msg); 
  18. }); 

如你所見,它只是簡單地返回一個函數,這個函數通過閉包訪問了傳給 partialApply() 函數的 fixedArgs 參數。

輪到你來試試了

你用閉包來做什么?如果你有最喜歡的應用場景,舉一些例子,在評論中告訴我。

責任編輯:武曉燕 來源: 今日頭條
相關推薦

2021-06-04 07:04:29

閉包JavaScript函數

2021-01-13 11:25:12

JavaScript閉包函數

2017-05-22 16:08:30

前端開發javascript閉包

2019-11-07 21:51:18

閉包前端函數

2021-02-21 16:21:19

JavaScript閉包前端

2022-01-18 08:16:52

Web 前端JavaScript

2020-10-14 15:15:28

JavaScript(

2011-05-25 14:48:33

Javascript閉包

2011-08-03 08:59:46

JavaScript

2016-09-14 09:20:05

JavaScript閉包Web

2009-07-24 17:30:37

Javascript閉

2017-02-08 10:54:38

JavaScriptVR世界

2017-09-14 13:55:57

JavaScript

2021-03-01 09:39:34

閉包JavaScript開發

2010-06-23 10:24:42

Javascript閉

2016-09-18 20:53:16

JavaScript閉包前端

2009-03-17 15:36:29

JavaScript循環事件

2012-11-29 10:09:23

Javascript閉包

2025-03-18 12:00:00

閉包JavaScript前端

2021-03-06 09:18:51

JS閉包函數
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产一级淫片a直接免费看 免费a网站 | 自拍偷拍视频网 | аⅴ资源新版在线天堂 | 蜜桃视频在线观看免费视频网站www | 99精品九九| 欧美性tv | 亚洲品质自拍视频网站 | 一区二区在线 | 一级毛片视频 | 国产一区二区三区久久久久久久久 | 国产精品成人一区二区三区 | 国产午夜精品一区二区三区四区 | 精品欧美激情精品一区 | 日日干夜夜操天天操 | 亚洲伊人精品酒店 | 国产精品毛片 | 中文字幕一区二区三区在线乱码 | 麻豆一区二区三区精品视频 | 亚洲一区二区三区免费视频 | 国产区精品视频 | 伊人免费在线观看 | 欧美福利 | 男人的天堂在线视频 | 精品国产欧美 | 中文字幕av亚洲精品一部二部 | 亚洲精色 | 午夜成人免费视频 | 日韩高清一区二区 | 精品日韩一区 | 欧美日韩国产高清 | 久综合| 国外成人在线视频网站 | 成人免费大片黄在线播放 | 玖玖久久 | 国产免费看 | 欧美日韩在线一区二区 | 亚洲精品在线免费观看视频 | 亚洲欧美日韩久久 | 在线看中文字幕 | 人人做人人澡人人爽欧美 | 日韩一区二区在线观看 |