首頁  >  文章  >  web前端  >  直擊JavaScript ES6裡最重要的5個特性

直擊JavaScript ES6裡最重要的5個特性

coldplay.xixi
coldplay.xixi轉載
2020-06-23 12:43:181968瀏覽

直擊JavaScript ES6裡最重要的5個特性

JavaScript ES6 增加了一系列新的語言特性,其中一些特性比其它更具開創性以及更廣泛的可用性。例如像 ES6 類別 這樣的特性,雖然新奇,但其實只是在 JavaScript 中創建類別的已有方法之上的一種語法糖。而像生成器(generator)這樣的功能,雖然非常強大,但卻是為了針對性的任務所保留的。

從過去的12個月所從事的不同 JavaScript 相關專案中,我發現有 5 個 ES6 特性是不可或缺的,因為它們真正簡化了 JavaScript 普通任務的完成方式。你心中的前 5 名可能和我的不一樣,如果是的話,我希望你能在結尾的評論區分享它們。

讓我們正式開始!

  1. 箭頭函數(Arrow Functions)
  2. Promises
  3. 異步函數(Async Functions)
  4. 解構(Destructuring)
  5. #預設和剩餘參數(Default and Rest Parameters)

1) JavaScript 箭頭函數

在ES6 JavaScript 中,我最喜歡的新增特性之一併不是一個全新特性,而是一個我每次使用都能讓我微笑的新文法。我說的是箭頭函數,它提供了一種極致優雅和簡潔的方式來定義匿名函數。

簡而言之,箭頭函數就是丟掉了關鍵字function,然後用一個箭頭=> 來分離一個匿名函數的參數部分和函數體:

(x, y) => x * y;

這相當於:

function(x, y){
    return x * y;
}

或:

(x, y) => {
    var factor = 5;
    var growth = (x-y) * factor;
}

完全等價於:

function(x, y){
    var factor = 5;
    var growth = (x-y) * factor;
}

在使用傳統的匿名函數時,箭頭函數也消除了一個關鍵的錯誤來源,即函數內的this 物件的值。使用箭頭函數,this 是基於詞法綁定,這僅僅是意味著它的值被綁定到父級作用域的一種奇特的方式,並且永遠不會改變。如果一個箭頭函數定義在一個自訂物件 countup 中,this 值毫無疑問地指向 countup。例如:

var countup = {
    counter: 15,

    start:function(){
        window.addEventListener('click', () => {
            alert(this.counter) // correctly alerts 15 due to lexical binding of this
        })
    }
};

countup.start();

比較傳統匿名函數,this 的值在哪變化取決於它被定義的上下文環境。當在上面的例子中嘗試引用 this.counter,結果將返回 undefined,這種行為可能會把很多不熟悉動態綁定的複雜性的人搞糊塗。使用箭頭函數,this 的值總是可預測且容易推斷的。

針對箭頭函數的詳細解說, 請看「Overview of JavaScript Arrow Functions「.

2) JavaScript Promises

JavaScript ES6 Promises 讓非同步任務的處理方式變成線性, 這是大多數現代網頁應用程式中的一項任務。而不是依靠回呼函數 —— 透過JavaScript框架(如jQuery)普及。 JavaScript Promises 使用一個中心直覺的機制來追蹤和回應非同步事件。它不僅使調試非同步程式碼變得更容易,而且使得編寫它也是一種樂趣。

所有JavaScript Promise 都是透過Promise() 建構子開始和結束:

const mypromise = new Promise(function(resolve, reject){
 // 在这编写异步代码
 // 调用 resolve() 来表示任务成功完成
 // 调用 reject() 来表示任务失败
})

在內部使用resolve() reject() 方法,當一個Promise 被完成或拒絕時,我們可以分別向一個Promise 物件發出訊號。 then()catch() 方法隨後可以被調用,用以處理完成或拒絕 Promise 後的工作。

我用下面一個被注入XMLHttpRequest 函數的Promise 的變種,來一個接一個的檢索外部文件內容:

function getasync(url) {
    return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest()
        xhr.open("GET", url)
        xhr.onload = () => resolve(xhr.responseText)
        xhr.onerror = () => reject(xhr.statusText)
        xhr.send()
    })
}

getasync('test.txt').then((msg) => {
    console.log(msg) // echos contents of text.txt
    return getasync('test2.txt')
}).then((msg) => {
    console.log(msg) // echos contents of text2.txt
    return getasync('test3.txt')
}).then((msg) => {
    console.log(msg) // echos contents of text3.txt
})

要掌握JavaScript Promises 的關鍵點,例如Promise 鍊和並行執行Promise,請閱讀「Beginner's Guide to Promises「.

3) JavaScript 非同步函數

除了JavaScript Promise,非同步函數進一步重寫了傳統的非同步程式碼結構,使其更具可讀性。每當我向客戶展示帶有async 程式設計功能的程式碼時,第一個反應總是令人驚訝,隨之而來的是了解它是如何運作的好奇心。

一個非同步函數由兩個部分構成:

1) 一個以async 為前綴的常規函數

async function fetchdata(url){
    // Do something
    // Always returns a promise
}

2) 在非同步函數(Async function)內,使用await 關鍵字呼叫非同步運算子

一個例子勝過千言萬語。以下是基於上面範例重寫的Promise,以便使用Async functions代替:

function getasync(url) { // same as original function
    return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest()
        xhr.open("GET", url)
        xhr.onload = () => resolve(xhr.responseText)
        xhr.onerror = () => reject(xhr.statusText)
        xhr.send()
    })
}

async function fetchdata(){ // main Async function
    var text1 = await getasync('test.txt')
    console.log(text1)
    var text2 = await getasync('test2.txt')
    console.log(text2)
    var text3 = await getasync('test3.txt')
    console.log(text3)
    return "Finished"
}

fetchdata().then((msg) =>{
    console.log(msg) // logs "finished"
})

上面的範例運行時會輸出“test.txt”,“test2.txt”,“test3 .txt”,最後是“Finished”。

如你所見,在非同步函數中,我們把非同步函數getasync() 當作是同步函數呼叫– 沒有then() 方法或回呼函數通知進行下一步。無論何時遇到關鍵字 await,執行都會暫停,直到 getasync() 解決,然後再轉到非同步函數中的下一行。結果與純粹的基於 Promise,使用一串 then 方法的方式一樣。

要掌握异步函数,包括如何 await 并行执行函数,请阅读 “Introduction to JavaScript Async Functions- Promises simplified”

4) JavaScript 解构

除了箭头函数,这是我每天使用最多的 ES6 功能。ES6 解构并非一个新功能,而是一个新的赋值语法,可以让您快速解压缩对象属性和数组中的值,并将它们分配给各个变量。

var profile = {name:'George', age:39, hobby:'Tennis'}
var {name, hobby} = profile // destructure profile object
console.log(name) // "George"
console.log(hobby) // "Tennis"

这里我用解构快速提取 profile 对象的 namehobby 属性 。

使用别名,你可以使用与你正在提取值的对象属性不同的变量名:

var profile = {name:'George', age:39, hobby:'Tennis'}
var {name:n, hobby:h} = profile // destructure profile object
console.log(n) // "George"
console.log(h) // "Tennis"

嵌套对象解构

解构也可以与嵌套对象一起工作,我一直使用它来快速解开来自复杂的JSON请求的值:

var jsondata = {
    title: 'Top 5 JavaScript ES6 Features',
    Details: {
        date: {
            created: '2017/09/19',
            modified: '2017/09/20',
        },
        Category: 'JavaScript',
    },
    url: '/top-5-es6-features/'
};

var {title, Details: {date: {created, modified}}} = jsondata
console.log(title) // 'Top 5 JavaScript ES6 Features'
console.log(created) // '2017/09/19'
console.log(modified) // '2017/09/20'

解构数组

数组的解构与在对象上的工作方式类似,除了左边的花括号使用方括号代替:

var soccerteam = ['George', 'Dennis', 'Sandy']
var [a, b] = soccerteam // destructure soccerteam array
console.log(a) // "George"
console.log(b) // "Dennis"

你可以跳过某些数组元素,通过使用逗号(,):

var soccerteam = ['George', 'Dennis', 'Sandy']
var [a,,b] = soccerteam // destructure soccerteam array
console.log(a) // "George"
console.log(b) // "Sandy"

对我而言,解构消除了传统方式提取和分配对象属性和数组值的所有摩擦。要充分掌握ES6解构的复杂性和潜力,请阅读”Getting to Grips with ES6: Destructuring“.

5) 默认和剩余参数(Default and Rest Parameters)

最后,我最想提出的ES6的两个特性是处理函数参数。几乎我们在JavaScript中创建的每个函数都接受用户数据,所以这两个特性在一个月中不止一次地派上用场。

默认参数(Default Parameters)

我们都使用过一下模式来创建具有默认值的参数:

function getarea(w,h){
  var w = w || 10
  var h = h || 15
  return w * h
}

有了ES6对默认参数的支持,显式定义的参数值的日子已经结束:

function getarea(w=10, h=15){
  return w * h
}
getarea(5) // returns 75

关于 ES6 默认参数的更多详情 在这.

剩余参数(Rest Parameters)

ES6中的 Rest Parameters 使得将函数参数转换成数组的操作变得简单。

function addit(...theNumbers){
  // get the sum of the array elements
    return theNumbers.reduce((prevnum, curnum) => prevnum + curnum, 0) 
}

addit(1,2,3,4) // returns 10

通过在命名参数前添加3个点 ...,在该位置和之后输入到函数中的参数将自动转换为数组。

没有 Rest Parameters, 我们不得不做一些复杂的操作比如 手动将参数转换为数组 :

function addit(theNumbers){
    // force arguments object into array
    var numArray = Array.prototype.slice.call(arguments) 
    return numArray.reduce((prevnum, curnum) => prevnum + curnum, 0)
}

addit(1,2,3,4) // returns 10

Rest parameters 只能应用于函数的参数的一个子集,就像下面这样,它只会将参数从第二个开始转换为数组:

function f1(date, ...lucknumbers){
    return 'The Lucky Numbers for ' + date + ' are: ' + lucknumbers.join(', ')
}

alert( f1('2017/09/29', 3, 32, 43, 52) ) // alerts "The Lucky Numbers for 2017/09/29 are 3,32,43,52"

对于 ES6 中 Rest Parameters 完整规范,看这里.

结论

你同意我所说的 ES6 特性的前五名吗?哪个是你最常用的,请在评论区和大家分享。

推荐教程:《javascript基础教程

以上是直擊JavaScript ES6裡最重要的5個特性的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:webhek.com。如有侵權,請聯絡admin@php.cn刪除