JavaScript >> Javascript 文檔 >  >> JavaScript

每個忙碌的 JavaScript 開發人員必須知道的 10 大 ES6 特性

我最近參加了在舊金山舉行的 HTML5 開發會議。我參加的演講中有一半是關於 ES6 的,或者現在正式稱為 ECMAScript2015。不過我更喜歡更簡潔的 ES6。

這篇文章將給你一個關於 ES6 的快速介紹。如果你不知道什麼是 ES6,它是一個新的 JavaScript 實現。如果您是一名忙碌的 JavaScript 軟件工程師(誰不是呢?),請繼續閱讀以了解新一代最流行的編程語言 JavaScript 的 10 個最佳特性。

以下是忙碌的軟件工程師的 10 大最佳 ES6 功能列表(排名不分先後):

  1. ES6 中的默認參數
  2. ES6 中的模板文字
  3. ES6 中的多行字符串
  4. ES6 中的解構賦值
  5. ES6 中增強的對象文字
  6. ES6 中的箭頭函數
  7. ES6 中的承諾
  8. 塊作用域構造 Let 和 Const
  9. ES6 中的類
  10. ES6 中的模塊

免責聲明:如果列表存在高度偏見和主觀性。這絕不是為了減少其他 ES6 功能的實用性,因為我不得不將數量限制為 10,所以沒有將其列入列表。

首先,有點歷史,因為那些不了解歷史的人是做不到的。這是一個簡短的 JavaScript 時間線:

  1. 1995 年:JavaScript 作為 LiveScript 誕生
  2. 1997:ECMAScript 標準建立
  3. 1999:ES3 出現,IE5 風靡一時
  4. 2000–2005:XMLHttpRequest,又名 AJAX,在 Outlook Web Access (2000) 和 Oddpost (2002)、Gmail (2004) 和 Google 地圖 (2005) 等應用程序中獲得普及。
  5. 2009:ES5 出現(這是我們大多數人現在使用的)forEach , Object.keys , Object.create (特別適用於 Douglas Crockford)和標準 JSON
  6. 2015:ES6/ECMAScript2015問世;它主要包含語法糖,因為人們無法就更突破性的東西達成一致(ES7?)

說完了歷史,讓我們進入編碼業務。

1。 ES6 中的默認參數

請記住,我們必須執行這些語句來定義默認參數:

var link = function (height, color, url) {
    var height = height || 50
    var color = color || 'red'
    var url = url || 'http://azat.co'
    ...
}

在值為 0 之前它們是可以的,並且因為 0 在 JavaScript 中是虛假的,它會默認為硬編碼值而不是成為值本身。當然,誰需要 0 作為值(#sarcasmfont),所以我們只是忽略了這個缺陷並使用邏輯 OR 無論如何......不再!在 ES6 中,我們可以將默認值直接放在函數的簽名中:

var link = function(height = 50, color = 'red', url = 'http://azat.co') {
  ...
}

順便說一句,這個語法和Ruby很像!

2。 ES6 中的模板文字

其他語言中的模板文字或插值是在字符串中輸出變量的一種方式。所以在 ES5 中我們不得不像這樣打破字符串:

var name = 'Your name is ' + first + ' ' + last + '.'
var url = 'http://localhost:3000/api/messages/' + id

幸運的是,在 ES6 中我們可以使用新的語法 ${NAME} 在反引號字符串內:

var name = `Your name is ${first} ${last}.`
var url = `http://localhost:3000/api/messages/${id}`

3。 ES6 中的多行字符串

另一個美味的語法糖是多行字符串。在 ES5 中,我們必須使用以下方法之一:

var roadPoem = 'Then took the other, as just as fair,\n\t'
    + 'And having perhaps the better claim\n\t'
    + 'Because it was grassy and wanted wear,\n\t'
    + 'Though as for that the passing there\n\t'
    + 'Had worn them really about the same,\n\t'

var fourAgreements = 'You have the right to be you.\n\
    You can only be you when you do your best.'

在 ES6 中,只需使用反引號:

var roadPoem = `Then took the other, as just as fair,
    And having perhaps the better claim
    Because it was grassy and wanted wear,
    Though as for that the passing there
    Had worn them really about the same,`

var fourAgreements = `You have the right to be you.
    You can only be you when you do your best.`

4。 ES6 中的解構賦值

解構可能是一個更難掌握的概念,因為有一些魔法正在發生……假設您有簡單的分配,其中鍵為 housemouse 是變量housemouse

[旁注]

閱讀博客文章很好,但觀看視頻課程更好,因為它們更具吸引力。

許多開發人員抱怨 Node.js 上缺乏負擔得起的高質量視頻材料。觀看 YouTube 視頻會讓人分心,花 500 美元購買 Node 視頻課程很瘋狂!

去看看 Node University,它有關於 Node 的免費視頻課程:node.university。

[旁注結束]

var data = $('body').data(), // data has properties house and mouse
  house = data.house,
  mouse = data.mouse

其他解構賦值示例(來自 Node.js):

var jsonMiddleware = require('body-parser').json

var body = req.body, // body has username and password
  username = body.username,
  password = body.password  

在 ES6 中,我們可以用這些語句替換上面的 ES5 代碼:

var {house, mouse} = $('body').data() // we'll get house and mouse variables

var {json: jsonMiddleware} = require('body-parser')

var {username, password} = req.body

這也適用於數組。瘋了!

var [col1, col2]  = $('.column'),
  [line1, line2, line3, , line5] = file.split('\n')

可能需要一些時間才能習慣解構賦值語法,但這是一種甜蜜的糖衣。

5。 ES6 中增強的對象文字

您現在可以用對象文字做的事情令人興奮!我們從 ES5 中的 JSON 的美化版本變成了與 ES6 中的類非常相似的東西。

這是一個帶有一些方法和屬性/屬性的典型 ES5 對象字面量:

var serviceBase = {port: 3000, url: 'azat.co'},
    getAccounts = function(){return [1,2,3]}

var accountServiceES5 = {
  port: serviceBase.port,
  url: serviceBase.url,
  getAccounts: getAccounts,
  toString: function() {
    return JSON.stringify(this.valueOf())
  },
  getUrl: function() {return "http://" + this.url + ':' + this.port},
  valueOf_1_2_3: getAccounts()
}

如果我們想要花哨,我們可以從 serviceBase 繼承 通過使用 Object.create 使其成為原型 方法:

var accountServiceES5ObjectCreate = Object.create(serviceBase)
var accountServiceES5ObjectCreate = {
  getAccounts: getAccounts,
  toString: function() {
    return JSON.stringify(this.valueOf())
  },
  getUrl: function() {return "http://" + this.url + ':' + this.port},
  valueOf_1_2_3: getAccounts()
}

我知道,accountServiceES5ObjectCreateaccountServiceES5 並不完全相同,因為一個對象(accountServiceES5 ) 將具有 __proto__ 中的屬性 對像如下圖:

ES6 中增強的對象字面量

但是為了這個例子,我們會認為它們是相似的。所以在 ES6 對象字面量中,有賦值 getAccounts: getAccounts, 的簡寫 變成getAccounts, .另外,我們在 __proto__`` property which makes sense (not 中設置了原型 ‘原型 '` 不過:

var serviceBase = {port: 3000, url: 'azat.co'},
    getAccounts = function(){return [1,2,3]}
var accountService = {
    __proto__: serviceBase,
    getAccounts,

另外,我們可以調用 super 並且有動態鍵(valueOf_1_2_3 ):

    toString() {
     return JSON.stringify((super.valueOf()))
    },
    getUrl() {return "http://" + this.url + ':' + this.port},
    [ 'valueOf_' + getAccounts().join('_') ]: getAccounts()
};
console.log(accountService)

ES6 II 中增強的對象文字

這是對良好的舊對象字面量的極大增強!

6。 ES6 中的箭頭函數

這可能是我最期待的一個功能。我喜歡 CoffeeScript 的粗箭頭。現在我們在 ES6 中有了它們。胖箭頭很神奇,因為它們會讓你的 this 行為正常,即 this 將具有與函數上下文中相同的值——它不會發生變異。每次創建閉包時通常都會發生突變。

在 ES6 中使用箭頭函數可以讓我們停止使用 that = thisself = this_this = this.bind(this) .比如 ES5 中的這段代碼就很難看:

var _this = this
$('.btn').click(function(event){
  _this.sendData()
})

這是沒有 _this = this 的 ES6 代碼 :

$('.btn').click((event) =>{
  this.sendData()
})

可悲的是,ES6 委員會認為擁有細箭頭對我們來說太過分了,他們給我們留下了一個冗長的舊 function 反而。 (CoffeeScript 中的細箭頭就像普通的 function 在 ES5 和 ES6 中)。

這是我們使用 call 的另一個示例 將上下文傳遞給 logUpperCase() ES5 中的函數:

var logUpperCase = function() {
  var _this = this

  this.string = this.string.toUpperCase()
  return function () {
    return console.log(_this.string)
  }
}

logUpperCase.call({ string: 'es6 rocks' })()

在 ES6 中,我們不需要弄亂 _this

var logUpperCase = function() {
  this.string = this.string.toUpperCase()
  return () => console.log(this.string)
}

logUpperCase.call({ string: 'es6 rocks' })()

請注意,您可以混合和匹配舊的 function 使用 => 在你認為合適的 ES6 中。而當箭頭函數與一行語句一起使用時,它就變成了一個表達式,即。它將隱式返回該單個語句的結果。如果你有不止一行,那麼你需要使用 return 明確的。

此 ES5 代碼正在從 messages 創建一個數組 數組:

var ids = ['5632953c4e345e145fdf2df8','563295464e345e145fdf2df9']
var messages = ids.map(function (value) {
  return "ID is " + value // explicit return
})

在 ES6 中會變成這個:

var ids = ['5632953c4e345e145fdf2df8','563295464e345e145fdf2df9']
var messages = ids.map(value => `ID is ${value}`) // implicit return

注意到我使用了字符串模板嗎? CoffeeScript 的另一個功能……我喜歡它們!

括號 () 對於箭頭函數簽名中的單個參數是可選的。當您使用多個參數時,您需要它們。

在 ES5 中,代碼有 function 顯式返回:

var ids = ['5632953c4e345e145fdf2df8', '563295464e345e145fdf2df9'];
var messages = ids.map(function (value, index, list) {
  return 'ID of ' + index + ' element is ' + value + ' ' // explicit return
})

以及更雄辯的 ES6 代碼版本,帶有括號和隱式返回:

var ids = ['5632953c4e345e145fdf2df8','563295464e345e145fdf2df9']
var messages = ids.map((value, index, list) => `ID of ${index} element is ${value} `) // implicit return

7。 ES6 中的承諾

承諾一直是一個有爭議的話題。有很多語法略有不同的 Promise 實現。 q、bluebird、deferred.js、vow、avow、jquery deferred 等等。其他人說我們不需要 Promise,只需使用異步、生成器、回調等。很高興,有一個標準的 Promise 現在在 ES6 中實現!

讓我們考慮一個使用 setTimeout() 的延遲異步執行的簡單示例 :

setTimeout(function(){
  console.log('Yay!')
}, 1000)

我們可以用 Promise 重寫 ES6 中的代碼:

var wait1000 =  new Promise(function(resolve, reject) {
  setTimeout(resolve, 1000)
}).then(function() {
  console.log('Yay!')
})

或者使用 ES6 箭頭函數:

var wait1000 =  new Promise((resolve, reject)=> {
  setTimeout(resolve, 1000)
}).then(()=> {
  console.log('Yay!')
})

到目前為止,我們已將代碼行數從三行增加到五行,但沒有任何明顯的好處。這是正確的。如果我們在 setTimeout() 中有更多的嵌套邏輯,好處就會出現 回調:

setTimeout(function(){
  console.log('Yay!')
  setTimeout(function(){
    console.log('Wheeyee!')
  }, 1000)
}, 1000)

可以用 ES6 Promise 重寫:

var wait1000 =  ()=> new Promise((resolve, reject)=> {setTimeout(resolve, 1000)})

wait1000()
  .then(function() {
    console.log('Yay!')
    return wait1000()
  })
  .then(function() {
    console.log('Wheeyee!')
  })

仍然不相信 Promises 比常規回調更好?我也不。我認為一旦你有了回調的想法並開始思考它們,那麼就不需要額外的複雜性了。

儘管如此,ES6 為喜歡它們的人提供了 Promises。 Promise 也有一個 fail-and-catch-all 回調,這是一個很好的特性。查看這篇文章以了解有關 Promises 的更多信息:ES6 Promises 簡介 .

8。塊作用域構造 Let 和 Const

你可能已經見過聽起來很奇怪的 let 在 ES6 代碼中。我記得我第一次在倫敦的時候,我被那些 TO LET 的標誌弄糊塗了。 ES6 let 與租用無關。這不是糖衣功能。它更複雜。 let 是一個新的 var 這允許將變量範圍限定為塊。我們用花括號定義塊。在 ES5 中,這些塊對 vars 沒有任何作用:

function calculateTotalAmount (vip) {
  var amount = 0
  if (vip) {
    var amount = 1
  }
  { // more crazy blocks!
    var amount = 100
    {
      var amount = 1000
      }
  }  
  return amount
}

console.log(calculateTotalAmount(true))

結果將是 1000。哇!這是一個非常糟糕的錯誤。在 ES6 中,我們使用 let 將範圍限制為塊。變量是函數作用域的。

function calculateTotalAmount (vip) {
  var amount = 0 // probably should also be let, but you can mix var and let
  if (vip) {
    let amount = 1 // first amount is still 0
  } 
  { // more crazy blocks!
    let amount = 100 // first amount is still 0
    {
      let amount = 1000 // first amount is still 0
      }
  }  
  return amount
}

console.log(calculateTotalAmount(true))

該值為 0,因為 if 塊也有 let .如果它什麼都沒有(amount=1 ),那麼表達式將是 1。

當涉及到 const ,事情變得更容易了;它只是一個不可變的,而且它也是塊範圍的,如 let .只是為了演示,這裡有一堆常量,它們都可以,因為它們屬於不同的塊:

function calculateTotalAmount (vip) {
  const amount = 0  
  if (vip) {
    const amount = 1 
  } 
  { // more crazy blocks!
    const amount = 100 
    {
      const amount = 1000
      }
  }  
  return amount
}

console.log(calculateTotalAmount(true))

在我看來,letconst 語言過於復雜。沒有它們,我們只有一種行為,現在有多種情況需要考慮。;-(

9。 ES6 中的類

如果您喜歡面向對象編程 (OOP),那麼您一定會喜歡這個功能。它使編寫類和從它們繼承就像在 Facebook 上點贊一樣簡單。

在 ES5 中創建和使用類是一件很痛苦的事情,因為沒有關鍵字 class (它被保留但什麼也沒做)。除此之外,許多繼承模式,如偽經典、經典、函數式,只會增加混亂,給 JavaScript 宗教戰爭的火上澆油。

我不會向你展示如何在 ES5 中編寫一個類(是的,是的,有類,對象繼承自對象),因為有很多種風格。讓我們馬上看一下 ES6 示例。我可以告訴你,ES6 類將使用原型,而不是函數工廠方法。我們有一個類 baseModel 我們可以在其中定義一個 constructor 和一個 getName() 方法:

class baseModel {
  constructor(options = {}, data = []) { // class constructor
    this.name = 'Base'
    this.url = 'http://azat.co/api'
    this.data = data
    this.options = options
  }

    getName() { // class method
      console.log(`Class name: ${this.name}`)
    }
}

請注意,我使用選項和數據的默認參數值。此外,方法名稱不需要包含單詞 function 或冒號 (: ) 了。另一個很大的區別是你不能分配屬性 this.NAME 與方法相同,即你不能說 name 在與方法相同的縮進級別。要設置屬性的值,只需在構造函數中賦值即可。

AccountModel 繼承自 baseModel 使用 class NAME extends PARENT_NAME

class AccountModel extends baseModel {
  constructor(options, data) {

要調用父構造函數,只需調用 super() 帶參數:

    super({private: true}, ['32113123123', '524214691']) //call the parent method with super
     this.name = 'Account Model'
     this.url +='/accounts/'
   }

如果你想真的很花哨,你可以像這樣設置一個getter和accountsData 將是一個屬性:

 get accountsData() { //calculated attribute getter
    // ... make XHR
    return this.data
  }
}

那麼你如何實際使用這個abracadabra?這就像誘使一個三歲的孩子認為聖誕老人是真的一樣容易:

let accounts = new AccountModel(5)
accounts.getName()
console.log('Data is %s', accounts.accountsData)

如果你想知道,輸出是:

Class name: Account Model
Data is %s 32113123123,524214691

10. ES6 中的模塊

正如你現在所看到的,在 ES6 之前的 JavaScript 中沒有原生模塊支持。人們想出了 AMD、RequireJS、CommonJS 和其他變通方法。現在有帶有 import 的模塊 和 export 操作數。

在 ES5 中你會使用 <script> 帶有 IIFE 或 AMD 等庫的標籤,而在 ES6 中,您可以使用 export 公開您的類 .我是一個 Node.js 人,所以我將使用 CommonJS,它也是一種 Node.js 語法。在帶有 Browserify 綁定的瀏覽器上使用 CommonJS 很簡單。假設我們有 port 變量和 getAccounts ES5 module.js 中的方法 :

module.exports = {
  port: 3000,
  getAccounts: function() {
    ...
  }
}

在 ES5 中 main.js ,我們將 require('module') 那個依賴:

var service = require('module.js')
console.log(service.port) // 3000

在 ES6 中,我們將使用 exportimport .例如,這是我們在 ES6 module.js 中的庫 文件:

export var port = 3000
export function getAccounts(url) {
  ...
}

在導入器 ES6 文件 main.js ,我們使用 import {name} from 'my-module' 句法。例如,

import {port, getAccounts} from 'module'
console.log(port) // 3000

或者我們可以將所有內容導入為變量 servicemain.js

import * as service from 'module'
console.log(service.port) // 3000

就個人而言,我發現 ES6 模塊令人困惑。是的,它們更有說服力,但 Node.js 模塊不會很快改變。瀏覽器和服務器 JavaScript 最好只有一種樣式,所以我現在還是堅持 CommonJS/Node.js 樣式。

瀏覽器中對 ES6 模塊的支持不會很快到來(在撰寫本文時),所以你需要像 jspm 這樣的東西來使用 ES6 模塊。

有關 ES6 模塊的更多信息和示例,請查看此文本。不管怎樣,寫模塊化的 JavaScript!

今天如何使用 ES6 (Babel)

ES6 已完成,但並非所有瀏覽器都完全支持(例如,ES6 Firefox 支持)。今天要使用 ES6,需要一個像 Babel 這樣的編譯器。您可以將其作為獨立工具運行或與您的構建系統一起使用。有 Grunt、Gulp 和 Webpack 的 Babel 插件。

今天如何使用 ES6(Babel)

這是一個 Gulp 示例。安裝插件:

$ npm install --save-dev gulp-babel

gulpfile.js ,定義一個任務build 這需要 src/app.js 並將其編譯成 build 文件夾:

var gulp = require('gulp'),
  babel = require('gulp-babel')

gulp.task('build', function () {
  return gulp.src('src/app.js')
    .pipe(babel())
    .pipe(gulp.dest('build'))
})

Node.js 和 ES6

對於 Node.js,您可以使用構建工具編譯 Node.js 文件或使用獨立的 Babel 模塊 babel-core .要安裝它,

$ npm install --save-dev babel-core

然後在 Node.js 中,調用這個函數:

require("babel-core").transform(es5Code, options)

ES6 事物總結

還有許多其他值得注意的 ES6 特性你可能不會使用(至少不會馬上使用)。排名不分先後:

  1. 新的數學、數字、字符串、數組和對象方法
  2. 二進制和八進制數類型
  3. 默認休息價差
  4. For of 推導式(你好,強大的 CoffeeScript!)
  5. 符號
  6. 尾調用
  7. 發電機
  8. Map 和 Set 等新數據結構

對於那些不能停止學習 ES6 的優秀者,比如一些在第一個薯片後就停不下來的人(再多一個!),以下是進一步閱讀的列表:

  1. ES6 備忘單(免費 PDF)
  2. 了解 ECMAScript 6 Nicolas Zakas 著書
  3. 探索 ES6 作者:Axel Rauschmayer 博士
  4. 節點大學的 ES6
  5. Node 大學的 ES7 和 ES8

Tutorial JavaScript 教程
  1. 在 Heroku 上使用 Flask 和 Twilio.js 構建一個應用程序以向國會發出基於瀏覽器的調用

  2. 執行上下文

  3. JavaScript 中的類型、值和變量

  4. 在 Svelte 中從 JSON 生成 CSV

  5. PHP vs Python:兩種語言之間的詳細比較

  6. 用於 JavaScript 中常見 Array 方法的 Polyfills

  7. 喵喵先生😹

  1. 一個簡單而有用的#react 組件,用於幫助異步加載/獲取數據

  2. 使用 Cypress 與 Next.js 和 Nx 對您的 React 組件進行戰鬥測試

  3. Mesfix 的 L4/高級開發人員

  4. Web 開發人員的 8 個有趣的項目創意

  5. 使用 jQuery,當用戶仍在編輯該字段時,如何將文本字段的第一個字母大寫?

  6. 使用 React 導航的 Auth 中間件

  7. 帶有 React 的打字稿

  1. 是的,這就是如何以 3 種獨特的方式將 Vue JS 與 WordPress 一起使用

  2. 用 Javascript 創建一個權重轉換器

  3. 彩色頭像泡泡

  4. 使用 App Engine 將 React 應用程序部署到 Google Cloud Platform