在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ HTML/ 箭頭函數(shù)
生成器
箭頭函數(shù)
繼續(xù)迭代器
未來前景
簡介
非結(jié)構(gòu)化賦值
迭代器和 for-of 循環(huán)
代理
符號
模版字符串
let 和 const
容器
模塊

箭頭函數(shù)

箭頭函數(shù)( Arrow Function )很早就被應(yīng)用在 JavaScript 中。第一版 JavaScript 教程中建議包裝腳本并內(nèi)嵌在 HTML 解釋中。這將會阻止瀏覽器不支持 JS 時,以文本形式錯誤地顯示你的 JS 代碼。你最好這樣寫:

<script language="javascript">
<!--
  document.bgColor = "brown";  // red
// -->
</script>

老的瀏覽器會認為上面的代碼是兩種不支持的標簽和解釋;只有新的瀏覽器會認為是 JS 代碼。

在你的瀏覽器中 JavaScript 引擎認為字符 <!-- 作為注釋的開始。不開玩笑地說,這真的是語言的一部分,并且直到現(xiàn)在,不僅僅是內(nèi)聯(lián)的頂部 <script> ,整個 JS 代碼任意部分都屬于語言的一部分。它甚至可以在節(jié)點處被執(zhí)行。

湊巧的是,這種注釋的風格是 ES6 首次標準化。但這不是我們談?wù)摰募^函數(shù)。

箭頭序列 --> 表示單行注釋。奇怪地是,在 HTML 中在字符串 --> 前面是注釋部分,而在 JS 中字符串 --> 后面的部分表示注釋。

令人感到奇怪的是,這個箭頭只有當它出現(xiàn)在一行的開始才表示注釋。這是因為在內(nèi)容的其它部分, --> 表示 JS 操作符, 表示 ”跳轉(zhuǎn)“操作符。

function countdown(n) {
  while (n --> 0)  // "n goes to zero"
    alert(n);
  blastoff();
}

這段代碼真的會工作。循環(huán)運行直到 n 變?yōu)?0 。 這也不是 ES6 的新特性,但是一個常見特征的組合。你能想象發(fā)生了什么嗎?像往常一樣,這個謎題的答案可以找到堆棧溢出。

當然,這里也有小于或等于操作符 <=。 或許你還可以在 JS代碼中發(fā)現(xiàn)更多的箭頭函數(shù)。讓我們停下來觀察這些箭頭函數(shù),發(fā)現(xiàn)有個箭頭函數(shù)消失了。

箭頭 說明
<!-- 單行注釋
--> ”跳轉(zhuǎn)”操作
<= 小于或等于操作符
=> ???

=>發(fā)生了什么呢?今天,讓我們來尋找它。

首先,讓我們來討論一些功能。

無處不在的函數(shù)表達式

JavaScript 的一個有趣特性是,任何時候你需要一個函數(shù),你可以在函數(shù)右邊加入運行代碼。

舉個例子,假設(shè)你試圖告訴瀏覽器當用戶點擊一個特殊按鈕后怎么處理。你可以輸入這樣的代碼:

$("#confetti-btn").click(

jQuery’s .click( ) 方法需要一個參數(shù):一個函數(shù)。毫無問題,你可以在函數(shù)右邊這樣輸入:

$("#confetti-btn").click(function (event) {
  playTrumpet();
  fireConfettiCannon();
});

像上面方式來寫代碼對于我們來說很自然。所以很好奇在 JavaScript 流行以前,很多語言都還不具備這種編程風格。當然 在 1958 年時,Lisp 語言已經(jīng)有了函數(shù)表達式,通常也被稱為 lambda 函數(shù)。 但是像 C++, Python, C# 和Java 存在很多年了都還沒有具備這種編程風格。

至少現(xiàn)在上述四種語言已經(jīng)具備了 lambda 函數(shù)。較新的語言通常都已經(jīng)內(nèi)置有l(wèi)ambda 函數(shù)了。我們能有現(xiàn)在的 JavaScript 應(yīng)該感謝早起的 JavaScript 開發(fā)者,他們創(chuàng)建了依賴于 lambdas 函數(shù)的函數(shù)庫,導致這一特征被廣泛采用。

這里有點略帶憂傷,在我提及的所有語言中, JavaScript 關(guān)于 lambdas 函數(shù)的介紹稍微有點冗長。

// A very simple function in six languages.
function (a) { return a > 0; } // JS
[](int a) { return a > 0; }  // C++
(lambda (a) (> a 0))  ;; Lisp
lambda a: a > 0  # Python
a => a > 0  // C#
a -> a > 0  // Java

一個新的箭頭函數(shù)

ES6 提供了新的語法規(guī)則來描述函數(shù)。

// ES5
var selected = allJobs.filter(function (job) {
  return job.isSelected();
});

// ES6
var selected = allJobs.filter(job => job.isSelected());

當你僅僅只需要帶有一個參數(shù)的函數(shù),這個新的箭頭函數(shù)語法簡單地描述為:標識符 => 表達式 ( Identifier => Expression ) 。你可以跳過編輯函數(shù)名和返回值,以及一些大括號,小括號和分號。

( 我個人非常感激這個特征。對于我來說,不用再次編輯函數(shù)很重要,因為我不可避免會輸錯函數(shù)名,這樣我不得不再回頭檢查并且改正。 )

在編寫一個帶有多個參數(shù)的函數(shù)時(或許沒有參數(shù),或許有默認參數(shù),或者是前面提到的非結(jié)構(gòu)化參數(shù)),你需要在參數(shù)列表的外面加一層括號。

// ES5
var total = values.reduce(function (a, b) {
  return a + b;
}, 0);

// ES6
var total = values.reduce((a, b) => a + b, 0);

我認為這樣的書寫那個時候看起來很美觀。

箭頭函數(shù)就像是在函數(shù)庫上編寫一樣, 顯得美觀。實際上,Immutable’s documentation 很多例子都是用 ES6 來編寫的,因此里面的很多例子都使用到了箭頭函數(shù)。

箭頭函數(shù)內(nèi)除了可以有表達式外,還可以有一段語句?;叵朐缙诘睦樱?/p>

// ES5
$("#confetti-btn").click(function (event) {
  playTrumpet();
  fireConfettiCannon();
});

這里是用 ES6 寫的代碼:

// ES6
$("#confetti-btn").click(event => {
  playTrumpet();
  fireConfettiCannon();
});

注意到一個箭頭函數(shù),用塊來描述的時候可能沒有自動返回一個值。我們可以用 return 聲明來返回。

這里有個注意事項當用箭頭函數(shù)來創(chuàng)建一個空對象時,要用括號括起來:

// create a new empty object for each puppy to play with
var chewToys = puppies.map(puppy => {});   // BUG!
var chewToys = puppies.map(puppy => ({})); // ok

不幸的是,一個空的對象 {} 和一個空塊 {} 看起來是一樣的。在 ES6 當中 { 緊跟在箭頭函數(shù)后面表示的是一個塊的開始,而不是一個對象的開始。這樣代碼 puppy => {} 表示的是一個箭頭函數(shù),什么都不做,空操作。返回一個未定義。

更令人困惑的是,像 {key: value} 這樣的對象聲明看起來像是一個包含有標簽的塊聲明。至少對你的 JavaScript 引擎來說是這樣的。幸運地是,你可以用括號將 { 這個歧義字符括起來。

什么是 this 指針?

普通的函數(shù)和箭頭函數(shù)還是存在細微的差別。箭頭函數(shù)沒有自己內(nèi)部的 this 指針。在箭頭函數(shù)中, this 指針是繼承于其所在的作用域。

讓我們在實際使用的過程中來搞明白這到底是什么意思。

在JavaScript 中 this 指針是怎么工作的?它的值又是來自哪里?這里沒有簡潔的答案。如果你認為這是很簡單的,那是因為你對于 this 指針已經(jīng)很熟悉了。

這一問題經(jīng)常出現(xiàn)的一個原因是 function 函數(shù)自動獲得 this 指針,不管你想要與否。你曾經(jīng)寫過這樣的代碼嗎?

{
  ...
  addAll: function addAll(pieces) {
    var self = this;
    _.each(pieces, function (piece) {
      self.add(piece);
    });
  },
  ...
}

這里你所寫的內(nèi)部函數(shù)是 this.add(piece)。不幸地是,這個內(nèi)部函數(shù)沒有繼承外部函數(shù)的 this 指針。這樣內(nèi)部的函數(shù)用 this 將會返回未定義。這個臨時的變量 self 會調(diào)用外部的 this 到內(nèi)部的函數(shù)來。( 另外一種方式在內(nèi)部函數(shù)中調(diào)用 .bind(this) 。其他方式都不是很令人滿意。 )

在 ES6 中, this 指針的 hacks 代碼可以避免如果你遵循下面的規(guī)則:

  • 用非箭頭函數(shù)方法,將使用 object.method() 語法。這樣函數(shù)將會從調(diào)用者那里獲得一個有意義的 this 指針。
  • 用箭頭函數(shù)。
// ES6
{
  ...
  addAll: function addAll(pieces) {
    _.each(pieces, piece => this.add(piece));
  },
  ...
}

ES6 版本中,注意到 addAll 方法從調(diào)用者那里獲得一個 this 指針。上面內(nèi)部的函數(shù)是一個箭頭函數(shù),它從作用域處繼承 this 指針。

作為獎勵, ES6 通常提供了一個更短的方式來描述對象! 因此上面的代碼可以變得更簡潔:

// ES6 with method syntax
{
  ...
  addAll(pieces) {
    _.each(pieces, piece => this.add(piece));
  },
  ...
}

比較上面的兩種方式,可以發(fā)現(xiàn)用箭頭函數(shù)描述可以不再輸入 function 了。這是一個很好的想法。

普通函數(shù)和箭頭函數(shù)還有一個小差異,那就是箭頭函數(shù)不需要參數(shù)。當然, 在 ES6 中,你可能寧愿用使用其他參數(shù)或者默認參數(shù)。

箭頭函數(shù)在計算科學的發(fā)展史

我們這里討論一些關(guān)于箭頭函數(shù)的實際應(yīng)用。這里我會討論一個用例: ES6 箭頭函數(shù)作為一個學習工具,來發(fā)現(xiàn)一些深層次的計算本質(zhì)。不管實際與否,你可以自己來判斷。

早在 1936 年,Alan Church 和 Alan Turing 獨立開發(fā)了具有強大計算功能的數(shù)學模型。Turing 稱它的模型為一個機器,即其余人所稱道的圖靈機。Church 的模型被他稱為 λ- 演算。( λ 是一個希臘小寫字母 lambda 。 )這也是為什么 Lisp 語言也用 LAMBDA 單詞來表示函數(shù)的原因,這也是今天我們稱函數(shù)表達式為 “l(fā)ambdas” 的原因。

但是什么又是 λ- 演算呢?什么又是計算模型的思想呢?

這里很難用幾句話來解釋,但是這里是我的一些嘗試性解釋: λ- 演算是最早的編程語言。它的目的不是為了設(shè)計編程語言——在此之后,直到十年或到二十年后的樣子才有了存儲程序計算機,但是相當簡單,它只能執(zhí)行一些你想要的純粹數(shù)學表達式。 Church 想讓他的模型能夠證明一些概括性的計算。

并且他只需要一樣東西在他的系統(tǒng)里就是:函數(shù)。

他的想法是多么的奇怪。沒有對象,沒有數(shù)組,沒有數(shù)字,還沒有 if 聲明, while 循環(huán) , 分號和賦值,還沒有邏輯操作符,或者是事件,這對于 JavaScript 來說是可能的,只用函數(shù)來重新構(gòu)建每種類型。

這里給出一個數(shù)學上的程序,用 Church’s 的 λ 表示法:

fix = λf.(λx.f(λv.x(x)(v)))(λx.f(λv.x(x)(v)))

與上面等價的 JavaScript 函數(shù)可以這樣來寫:

var fix = f => (x => f(v => x(x)(v)))
               (x => f(v => x(x)(v)));

也就是說, JavaScript 包含了一個實現(xiàn) λ- 演算的部分。 即 λ- 演算在JavaScript 中。

關(guān)于 Alonzo Church 和后續(xù)的研究者關(guān)于 λ- 演算做的研究,以及它揭示了 λ- 演算如何成為大多數(shù)語言中的一部分,這些內(nèi)容超出了這一章節(jié)的范圍。但是如果你對計算機科學的起源很感興趣,或者你對一個語言最開始只有函數(shù)沒有任何其他類型感興趣,你可以花費你雨天的中午來閱讀 Church numeralsfixed-point combinator,并且你還可以在你的 Firefox 控制臺上寫。由于 ES6 在箭頭函數(shù)方面的優(yōu)勢, JavaScript 可以合理地聲明自己的語言對于探索 λ- 演算是最好的語言。

我們什么時候能夠用箭頭函數(shù)?

ES6 的箭頭函數(shù)是由我于 2013 年在 Firefox 中實現(xiàn)。 Jan de Mooij 使得箭頭函數(shù)運行變得更快。感謝 Tooru Fujisawa 和 ziyunfei 提供補丁。

箭頭函數(shù)也在微軟的新版本中實現(xiàn)。他們也在 BabelTraceur,和 TypeScript 得到實現(xiàn),如果你對于在網(wǎng)上使用箭頭函數(shù)很感興趣。

在下一章節(jié)中我們又會討論 ES6 的一個奇怪用法。我們將看到 typeof x 會返回一個全新的值。我們將會發(fā)問:到底什么時候是一個名稱什么時候又是一個字符串呢?我們會努力思考這些問題。這些都令人感到新奇。所以請下周繼續(xù)加入我們來深度探索 ES6 關(guān)于符號的新特征。

下一篇:模塊