ES6(ECMAScript2022)的出現,無疑給前端開發人員帶來了新的驚喜,它包含了一些很棒的新特性,可以更加方便的實現很多複雜的操作,提高開發人員的效率。
WordPress 網站建設小編主要針對 ES6 做一個簡要介紹。也許您還不知道 ES6 是什麼, 實際上, 它是一種新的 javascript 規範。在這個大家都很忙碌的時代,如果您想對 ES6 有一個快速的瞭解,那麼請繼續往下讀,去了解當今流行的程式語言 JavaScript 新一代的十大特性。
以下是 ES6 排名前
ES6(ECMAScript2022)的出現,無疑給前端開發人員帶來了新的驚喜,它包含了一些很棒的新特性,可以更加方便的實現很多複雜的操作,提高開發人員的效率。
本文主要針對 ES6 做一個簡要介紹。 WordPress 網站建設也許您還不知道 ES6 是什麼, 實際上, 它是一種新的 javascript 規範。在這個大家都很忙碌的時代,如果您想對 ES6 有一個快速的瞭解,那麼請繼續往下讀,去了解當今流行的程式語言 JavaScript 新一代的十大特性。
以下是 ES6 排名前十的理想特性列表(排名不分先後):
Default Parameters(預設引數)in ES6
Template Literals(模板文字)in ES6
Multi-line Strings(多行字串)in ES6
Destructuring Assignment(解構賦值)in ES6
Enhanced Object Literals(增強的物件文字)in ES6
Arrow Functions(箭頭函式)in ES6
Promises in ES6
Block-Scoped Constructs Let and Const(塊作用域構造 Let and Const)
Classes(類)in ES6
Modules(模組)in ES6
宣告:這些列表僅是個人主觀意見。它絕不是為了削弱 ES6 其它功能,這裡只列出了 10 條比較常用的特性。
先回顧一下 JavaScript 的歷史,不清楚歷史的人,很難理解 JavaScript 為什麼會這樣發展。下面就是一個簡單的 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 Maps (2005) 大受重用。
5 、 2009: ES5 出現,(就是我們大多數人現在使用的)例如 foreach,Object.keys,Object.create 和 JSON 標準。
6 、 2022:ES6/ECMAScript2022 出現。
歷史回顧就先到此,現讓我們進入正題。
1.Default Parameters(預設引數)in ES6
還記得我們以前不得不透過下面方式來定義預設引數:
1
2
3
4
5
6
var link = function (height, color, url) {
var height = height || 50;
var color = color || ‘red’;
var url = url || ‘http://azat.co’;
…
}
一切工作都是正常的,直到引數值是 0 後,就有問題了,因為在 JavaScript 中,0 表示 fasly,它是預設被 hard-coded 的值,而不能變成引數本身的值。當然,如果您非要用 0 作為值,我們可以忽略這一缺陷並且使用邏輯 OR 就行了!但在 ES6,我們可以直接把預設值放在函式申明裡:
1
2
3
var link = function(height = 50, color = ‘red’, url = ‘http://azat.co’) {
…
}
順便說一句,這個語法類似於 Ruby!
2.Template Literals(模板物件)in ES6
在其它語言中,使用模板和插入值是在字串裡面輸出變數的一種方式。因此,在 ES5,我們可以這樣組合一個字串:
1
2
var name = ‘Your name is ‘ + first + ‘ ‘ + last + ‘.’;
var url = ‘http://localhost:3000/api/messages/’ + id;
幸運的是,在 ES6 中,我們可以使用新的語法 $ {NAME},並把它放在反引號裡:
1
2
var name = `Your name is ${first} ${last}. `;
var url = `http://localhost:3000/api/messages/${id}`;
3.Multi-line Strings(多行字串)in ES6
ES6 的多行字串是一個非常實用的功能。在 ES5 中,我們不得不使用以下方法來表示多行字串:
1
2
3
4
5
6
7
var roadPoem = ‘Then took the other, as just as fair,nt’
+ ‘And having perhaps the better claimnt’
+ ‘Because it was grassy and wanted wear,nt’
+ ‘Though as for that the passing therent’
+ ‘Had worn them really about the same,nt’;
var fourAgreements = ‘You have the right to be you.n
You can only be you when you do your best.’;
然而在 ES6 中,僅僅用反引號就可以解決了:
1
2
3
4
5
6
7
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.Destructuring Assignment(解構賦值)in ES6
解構可能是一個比較難以掌握的概念。先從一個簡單的賦值講起,其中 house 和 mouse 是 key,同時 house 和 mouse 也是一個變數,在 ES5 中是這樣:
1
2
3
var data = $(‘body’).data(), // data has properties house and mouse
house = data.house,
mouse = data.mouse;
以及在 node.js 中用 ES5 是這樣:
1
2
3
4
var jsonMiddleware = require(‘body-parser’).jsonMiddleware ;
var body = req.body, // body has username and password
username = body.username,
password = body.password;
在 ES6,我們可以使用這些語句代替上面的 ES5 程式碼:
1
2
3
var { house, mouse} = $(‘body’).data(); // we’ll get house and mouse variables
var {jsonMiddleware} = require(‘body-parser’);
var {username, password} = req.body;
這個同樣也適用於陣列,非常讚的用法:
1
2
var [col1, col2] = $(‘.column’),
[line1, line2, line3, , line5] = file.split(‘n’);
我們可能需要一些時間來習慣解構賦值語法的使用,但是它確實能給我們帶來許多意外的收穫。
5.Enhanced Object Literals(增強的物件字面量)in ES6
使用物件文字可以做許多讓人意想不到的事情!透過 ES6,我們可以把 ES5 中的 JSON 變得更加接近於一個類。
下面是一個典型 ES5 物件文字,裡面有一些方法和屬性:
1
2
3
4
5
6
7
8
9
10
11
12
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()
}
如果我們想讓它更有意思,我們可以用 Object.create 從 serviceBase 繼承原型的方法:
1
2
3
4
5
6
7
8
9
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()
}
我們知道,accountServiceES5ObjectCreate 和 accountServiceES5 並不是完全一致的,因為一個物件 (accountServiceES5) 在__proto__物件中將有下面這些屬性:
為了方便舉例,我們將考慮它們的相似處。所以在 ES6 的物件文字中,既可以直接分配 getAccounts: getAccounts, 也可以只需用一個 getAccounts,此外,我們在這裡透過__proto__(並不是透過’proto’)設定屬性,如下所示:
1
2
3
4
5
var serviceBase = {port: 3000, url: ‘azat.co’},
getAccounts = function(){return [1,2,3]};
var accountService = {
__proto__: serviceBase,
getAccounts,
另外,我們可以呼叫 super 防範,以及使用動態 key 值 (valueOf_1_2_3):
1
2
3
4
5
6
7
toString() {
return JSON.stringify((super.valueOf()));
},
getUrl() {return “http://” + this.url + ‘:’ + this.port},
[ ‘valueOf_’ + getAccounts().join(‘_’) ]: getAccounts()
};
console.log(accountService)
ES6 物件文字是一個很大的進步對於舊版的物件文字來說。
6.Arrow Functions in(箭頭函式)ES6
這是我迫不及待想講的一個特徵,CoffeeScript 就是因為它豐富的箭頭函式讓很多開發者喜愛。在 ES6 中,也有了豐富的箭頭函式。這些豐富的箭頭是令人驚訝的因為它們將使許多操作變成現實,比如,
以前我們使用閉包,this 總是預期之外地產生改變,而箭頭函式的迷人之處在於,現在您的 this 可以按照您的預期使用了,身處箭頭函式裡面,this 還是原來的 this 。
有了箭頭函式在 ES6 中, 我們就不必用 that = this 或 self = this 或 _this = this 或.bind(this) 。例如,下面的程式碼用 ES5 就不是很優雅:
1
2
3
4
var _this = this;
$(‘.btn’).click(function(event){
_this.sendData();
})
在 ES6 中就不需要用 _this = this:
1
2
3
$(‘.btn’).click((event) =>{
this.sendData();
})
不幸的是,ES6 委員會決定,以前的 function 的傳遞方式也是一個很好的方案,所以它們仍然保留了以前的功能。
下面這是一個另外的例子,我們透過 call 傳遞文字給 logUpperCase() 函式在 ES5 中:
1
2
3
4
5
6
7
8
9
10
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 浪費時間:
1
2
3
4
5
var logUpperCase = function() {
this.string = this.string.toUpperCase();
return () => console.log(this.string);
}
logUpperCase.call({ string: ‘ES6 rocks’ })();
請注意,只要您願意,在ES6中=>可以混合和匹配老的函式一起使用。當在一行程式碼中用了箭頭函式,它就變成了一個表示式。它將暗地裡返回單個語句的結果。如果您超過了一行,將需要明確使用 return 。
這是用 ES5 程式碼建立一個資訊陣列:
1
2
3
4
var ids = [‘5632953c4e345e145fdf2df8′,’563295464e345e145fdf2df9’];
var messages = ids.map(function (value) {
return “ID is ” + value; // explicit return
});
用 ES6 是這樣:
1
2
var ids = [‘5632953c4e345e145fdf2df8′,’563295464e345e145fdf2df9’];
var messages = ids.map(value => `ID is ${value}`); // implicit return
請注意,這裡用了字串模板。
在箭頭函式中,對於單個引數,括號 () 是可選的,但當您超過一個引數的時候您就需要他們。
在 ES5 程式碼有明確的返回功能:
1
2
3
4
var ids = [‘5632953c4e345e145fdf2df8’, ‘563295464e345e145fdf2df9’];
var messages = ids.map(function (value, index, list) {
return ‘ID of ‘ + index + ‘ element is ‘ + value + ‘ ‘; // explicit return
});
在 ES6 中有更加嚴謹的版本,引數需要被包含在括號裡並且它是隱式的返回:
1
2
var ids = [‘5632953c4e345e145fdf2df8′,’563295464e345e145fdf2df9’];
var messages = ids.map((value, index, list) => `ID of ${index} element is ${value} `); // implicit return
7. Promises in ES6
Promises 是一個有爭議的話題。因此有許多略微不同的 promise 實現語法。 Q,bluebird,deferred.js,vow, avow, jquery 一些可以列出名字的。也有人說我們不需要 promises,僅僅使用非同步,生成器,回撥等就夠了。但令人高興的是,在 ES6 中有標準的 Promise 實現。
下面是一個簡單的用 setTimeout() 實現的非同步延遲載入函式:
1
2
3
setTimeout(function(){
console.log(‘Yay!’);
}, 1000);
在 ES6 中,我們可以用 promise 重寫:
1
2
3
4
5
var wait1000 = new Promise(function(resolve, reject) {
setTimeout(resolve, 1000);
}).then(function() {
console.log(‘Yay!’);
});
或者用 ES6 的箭頭函式:
1
2
3
4
5
var wait1000 = new Promise((resolve, reject)=> {
setTimeout(resolve, 1000);
}).then(()=> {
console.log(‘Yay!’);
});
到目前為止,程式碼的行數從三行增加到五行,並沒有任何明顯的好處。確實,如果我們有更多的巢狀邏輯在 setTimeout() 回撥函式中,我們將發現更多好處:
1
2
3
4
5
6
setTimeout(function(){
console.log(‘Yay!’);
setTimeout(function(){
console.log(‘Wheeyee!’);
}, 1000)
}, 1000);
在 ES6 中我們可以用 promises 重寫:
1
2
3
4
5
6
7
8
9
var wait1000 = ()=> new Promise((resolve, reject)=> {setTimeout(resolve, 1000)});
wait1000()
.then(function() {
console.log(‘Yay!’)
return wait1000()
})
.then(function() {
console.log(‘Wheeyee!’)
});
還是不確信 Promises 比普通回撥更好?其實我也不確信,我認為一旦您有回撥的想法,那麼就沒有必要額外增加 promises 的複雜性。
雖然,ES6 有讓人崇拜的 Promises 。 Promises 是一個有利有弊的回撥但是確實是一個好的特性,更多詳細的資訊關於 promise:Introduction to ES6 Promises.
8.Block-Scoped Constructs Let and Const(塊作用域和構造 let 和 const)
在 ES6 程式碼中,您可能已經看到那熟悉的身影 let 。在 ES6 裡 let 並不是一個花俏的特性,它是更復雜的。 Let 是一種新的變數申明方式,它允許您把變數作用域控制在塊級裡面。我們用大括號定義程式碼塊,在 ES5 中,塊級作用域起不了任何作用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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,這真是一個 bug 。在 ES6 中,我們用 let 限制塊級作用域。而 var 是限制函式作用域。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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,因為塊作用域中有了 let 。如果(amount=1). 那麼這個表示式將返回 1 。談到 const,就更加容易了;它就是一個不變數,也是塊級作用域就像 let 一樣。下面是一個演示,這裡有一堆常量,它們互不影響,因為它們屬於不同的塊級作用域:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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));
從我個人看來,let 和 const 使這個語言變複雜了。沒有它們的話,我們只需考慮一種方式,現在有許多種場景需要考慮。
9. Classes(類)in ES6
如果您喜歡物件導向程式設計(OOP),那麼您將喜愛這個特性。以後寫一個類和繼承將變得跟在 facebook 上寫一個評論那麼容易。
類的建立和使用真是一件令人頭疼的事情在過去的 ES5 中,因為沒有一個關鍵字 class(它被保留,但是什麼也不能做)。在此之上,大量的繼承模型像 pseudo classical, classical, functional 更加增加了混亂,JavaScript 之間的宗教戰爭只會更加火上澆油。
用 ES5 寫一個類,有很多種方法,這裡就先不說了。現在就來看看如何用 ES6 寫一個類吧。 ES6 沒有用函式, 而是使用原型實現類。我們建立一個類 baseModel ,並且在這個類裡定義了一個 constructor 和一個 getName() 方法:
1
2
3
4
5
6
7
8
9
10
11
12
class baseModel {
constructor(options, data) { // class constructor,node.js 5.6 暫時不支援 options = {}, data = [] 這樣傳參
this.name = ‘Base’;
this.url = ‘http://azat.co/api’;
this.data = data;
this.options = options;
}
getName() { // class method
console.log(`Class name: ${this.name}`);
}
}
注意我們對 options 和 data 使用了預設引數值。此外方法名也不需要加 function 關鍵字,而且冒號 (:) 也不需要了。另外一個大的區別就是您不需要分配屬性 this 。現在設定一個屬性的值,只需簡單的在建構函式中分配。
AccountModel 從類 baseModel 中繼承而來:
1
2
class AccountModel extends baseModel {
constructor(options, data) {
為了呼叫父級建構函式,可以毫不費力的喚起 super() 用引數傳遞:
1
2
3
4
super({private: true}, [‘32113123123’, ‘524214691’]); //call the parent method with super
this.name = ‘Account Model’;
this.url +=’/wp-content/uploads/sites/3/accounts/’;
}
如果您想做些更好玩的,您可以把 accountData 設定成一個屬性:
1
2
3
4
5
get accountsData() { //calculated attribute getter
// … make XHR
return this.data;
}
}
那麼,您如何呼叫他們呢?它是非常容易的:
1
2
3
let accounts = new AccountModel(5);
accounts.getName();
console.log(‘Data is %s’, accounts.accountsData);
結果令人驚訝,輸出是:
Class name: Account Model
Data is 32113123123,524214691
10. Modules(模組)in ES6
眾所周知,在 ES6 以前 JavaScript 並不支援本地的模組。人們想出了 AMD,RequireJS,CommonJS 以及其它解決方法。現在 ES6 中可以用模組 import 和 export 操作了。
在 ES5 中,您可以在 Weixiaoduo.com , All Rights Reserved . ICP證:陝15002899 .