ECMAScript 6.0(如下簡稱 ES6)是 JavaScript 語言的下一代標準,正式發佈與2015年6月。它的目標,是使得JavaScript語言能夠用來編寫複雜的大型應用程序,成爲企業級開發語言。javascript
ECMAScript 6,即所謂的現代Javascript,具備強大的功能,例如塊做用域、類、箭頭功、生成器以及許多其餘有用的功能。php
在vue應用開發中使用的全部必要功能來改善編程體驗,提升開發效率及代碼質量。經過vue CLI的Babel或core-js集成,使開發中的代碼嚴格按照配置規範進行迭代,有助於團隊協做。vue
ES6最基本的功能:let和const。java
let與var相似,但使用let聲明的變量的做用域是在聲明它們的塊中。(Block指條件塊,for循環塊等)程序員
例如,在條件塊中使用let將在塊內做用域變量,在塊外不可用。typescript
if (true) { let foo = "word"; } console.log(foo); // error
在這裏,錯誤是一件好事,由於它能夠防止在生產過程當中發生潛在的錯誤。編程
若是在上面的例子中使用var(就像在傳統的Javascript代碼中那樣)而不是let,就不會出現錯誤。數組
const是另外一個用於聲明變量的ES6關鍵字。不一樣之處在於const建立的變量在聲明以後不能更改,這個特色能夠有效的避免BUG的出現,所以在編寫代碼過程當中,建議儘可能寫純函數(純函數,就是給定函數固定的輸入,輸出的結果就是固定的,不會受函數外的變量等的影響)。promise
例如:ruby
const a = 2021 a = 2020 // error
有幾種建立變量的方法,咱們應該使用哪種?
最好的作法是儘量使用const。只有當你須要一個之後須要更改的變量時才使用let,好比在for循環中。
說到循環,在ES6語法中有一種更簡單的方法來編寫for循環,甚至不須要使用let。
例如,一個傳統的for循環是這樣的:
const arr = [1, 2, 3]; for (let i = 0; i < arr.length; i++) { const item = arr[i]; console.log(item); }
在ES6中,很是簡單:
const arr = [1, 2, 3]; for (const item of arr) { console.log(item); }
不要與for..in語法混淆;他們是徹底不一樣的東西。 for..in將得到數組/對象中的屬性,而for..of將得到實際想要迭代的數據。
可迭代對象是實現可迭代協議的任何對象。(協議只是指須要經過在對象中使用特定名稱的特定方法來知足的需求。)
例如,下面是一個實現了iterable協議的對象:
const twice = { [Symbol.iterator]() { let i = 0; const iterator = { next() { if (i < 2) { return { value: i++, done: false }; } else { return { value: undefined, done: true }; } }, }; return iterator; }, };
如今能夠在for..of循環中使用此twice對象:
for(const x of twice){ console.log(x) }
這會對twice對象進行兩次循環,分別獲得0和1。
爲了建立一個可迭代對象,實際上實現了兩個協議,iterable協議和iterator協議。
爲了知足做爲可迭代對象的要求,須要一個名爲[Symbol.iterator]的方法。
const twice = {
[Symbol.iterator]() { ... } }
方法名中應用了兩個新的ES6技巧。
首先,Symbol.iterator 一個內置的符號值,而Symbol是ES6中用於建立惟一標籤/標識符的基本類型。
其次,包裝屬性鍵的方括號使它成爲一個動態計算的鍵。這裏的關鍵是表達式符號。迭代器將被求值爲,一般不關心實際的求值是什麼。這個不重要的細節被抽象掉了。
這就是可迭代的協議。如今仍然須要處理迭代器協議來建立可迭代的對象,由於必須從 [Symbol.iterator] 函數返回一個迭代器
迭代器協議更簡單。只須要一個對象有一個next方法便可返回帶有兩個鍵的對象:value和done。當要中止迭代時,只需返回對象{value:undefined,done:true}。
這是示例中的迭代器:
const iterator = {
next() {
if (i < 2) { return { value: i++, done: false }; } else { return { value: undefined, done: true }; } }, };
總之,有一個同時知足可迭代協議和迭代器協議的對象。如如下代碼:
const twice = { [Symbol.iterator]() { let i = 0; const iterator = { next() { if (i < 2) { return { value: i++, done: false }; } else { return { value: undefined, done: true }; } }, }; return iterator; }, };
數組和字符串可使用for..of,進行迭代。這意味着這些內置類型包含與上面的相似的[Symbol.iterator]方法。
與迭代相關的另外一個功能是生成器。
上面的可迭代代碼依靠閉包來存儲 i 變量。使用 generator 時,沒必要擔憂本身構造閉包:
function* twiceGen() { let i = 0; while (i < 2) { yield i; i++; } } const twice = twiceGen();
該代碼實現了與可迭代示例相同的行爲,但更爲簡單。
能夠與for..of徹底相同地使用它:
for(const item of twice){ console.log(item) }
如你所見,它是一個帶有星號(*)聲明的函數。它使用yield關鍵字逐個抽取值,就像迭代器的next方法同樣。
生成器是一種多功能工具,基本上,它是一種容許暫停/恢復功能的機制。沒必要在for..of中使用上述twice對象。能夠調用它的next方法。
function* twiceGen() { const i = 0; while (i < 2) { yield i; } } const twice = twiceGen(); twice.next().value; // 0
此時,twiceGen函數在第一次運行while循環後暫停。若是再次運行相同的操做,它將恢復並播放循環的第二次運行。
twice.next().value; // 1
生成器的妙處在於它還建立了一個可迭代的迭代器對象。這就是爲何咱們可以使用for..of(可迭代特權)迭代兩次並直接調用其next方法(迭代器特權)的緣由。
可能不會當即建立本身的迭代器、生成器,因此讓咱們來看看其餘一些ES6的首創性,它們能夠當即使你的代碼更加友好。
就像許多其餘編程語言同樣,如今能夠爲函數參數設置默認值。
過去是這樣實現默認值的:
function addOne(num) { if (num === undefined) { num = 0; } return num + 1; } addOne();
如今能夠這樣:
function addOne(num = 0) { return num + 1; } addOne();
解構賦值語法是一種 Javascript 表達式。經過解構賦值, 能夠將屬性/值從對象/數組中取出,賦值給其餘變量。
若是要將對象傳遞給函數,則能夠輕鬆選擇對象的屬性,而後使用ES6分解語法將它們放在單獨的變量中:
function foo({ a, b }) { console.log(a, b); // 1, 2 } foo({ a: 1, b: 2 });
這種解構語法的好處是能夠避免建立帶有附加代碼行的變量。所以不須要像下面這樣:
function foo(obj) { const a = obj.a; const b = obj.b; console.log(a, b); // 1, 2 }
一樣,還能夠在解構語法中設置默認值:
function foo({ a = 0, b }) { console.log(a, b); // 0, 2 } foo({ b: 2 });
解構語法也適用於賦值:
function foo(obj) { const { a, b } = obj; console.log(a, b); // 1, 2 }
當從參數之外的地方獲取對象時,這也頗有用。
function getObj() { return { a: 1, b: 2 }; } function foo() { const { a, b } = getObj(); console.log(a, b); // 1, 2 }
解構技巧一樣也適用數組。
解構參數:
function foo([a, b]) { console.log(a, b); // 1, 2 } foo([1, 2, 3]);
解構賦值:
function foo(arr) { const [a, b] = arr; console.log(a, b); // 1, 2 }
在解構數組時,可使用 ... 語法來獲取數組中的全部其餘項。
function foo([a, b, ...c]) { console.log(c); // [3, 4, 5] } foo([1, 2, 3, 4, 5]);
c如今是一個包含本身的數組,包含了其他的元素:3,4,5。這裏的操做就是Rest操做。
這個語法一樣適用於賦值:
function foo(arr) { const [a, b, ...c] = arr; console.log(c); // [3, 4, 5] } foo([1, 2, 3, 4, 5]);
rest操做符也能夠單獨使用,無需解構:
function foo(...nums) { console.log(nums); // [1, 2, 3, 4, 5] } foo(1, 2, 3, 4, 5);
在這裏,咱們將數字做爲獨立參數傳遞,而不是做爲單個數組傳遞。可是在函數內部,使用rest運算符將數字做爲單個數組收集。當遍歷這些參數時,這頗有用。
rest語法 ... 與另外一個ES6特性操做符擴展徹底相同。
例如,若是要將兩個數組合併爲一個:
const a = [1, 2]; const b = [3, 4]; const c = [...a, ...b]; console.log(c); // [1, 2, 3, 4]
spread操做符用於將全部項展開,並將它們放入不一樣的數組中。
spread也適用於對象:
const obj = { a: 1, b: 2 }; const obj2 = { ...obj, c: 3 }; console.log(obj2); // { a: 1, b: 2, c: 3 }
如今,第二個對象除了其自身的屬性外,還應包含第一個對象的全部內容。
ES6提供了建立函數,對象和類的更簡單方法。
箭頭函數表達式的語法比函數表達式更簡潔,而且沒有本身的this,arguments,super或new.target。箭頭函數表達式更適用於那些原本須要匿名函數的地方,而且它不能用做構造函數。
使用箭頭語法來建立更簡潔的函數:
const addOne = (num) => { return num + 1; };
箭頭語法對於建立單行函數更加簡潔友好。
const addOne = (num) => num + 1;
此函數將自動返回表達式num +1的求值做爲返回值,不須要顯式的使用return關鍵字。
若是函數僅接受一個參數,甚至能夠省略括號(可是在嚴格語法上仍是建議加上括號):
const addOne = num => num + 1;
可是若是沒有任何參數,仍然須要一對空括號:
const getNum = () => 1;
可是,此語法有一個警告,若是咱們返回的是對象字面量,則沒法使用,會報錯:
const getObj = () => { a: 1, b: 2 } // error
這將產生語法錯誤,由於解析器將假定花括號用於函數塊,而不是對象字面量。
爲了不這個錯誤,必須將對象字面量包裝在一對括號中:
const getObj = () => ({ a: 1, b: 2 });
另外一件須要記住的事情是,this關鍵字不能在箭頭函數中使用。它不會出現錯誤;相反,它只會從周圍的範圍提供相同的this引用。
function thatOrThis() { const that = this; const compare = () => { console.log(that === this); // true }; compare(); } thatOrThis();
以上代碼給出的值則爲:true
ES6也提供了一種更簡單的方法來建立對象字面量。
若是在一個對象中放入兩個項目,它們的屬性鍵與變量相同,能夠用傳統的Javascript作這樣的事情:
const a = 1; const b = 2; const obj = { a: a, b: b, };
可是在ES6中,語法能夠更簡單:
const a = 1; const b = 2; const obj = { a, b };
若是把方法放到對象字面量中,能夠這樣作:
const a = 1; const b = 2; const obj = { a, b, getA() { return this.a; }, getB() { return this.b; }, };
基本上,沒有function關鍵字和冒號。
ES6提供了相似於其餘面嚮對象語言的類構造。如今沒必要依賴於混淆構造函數和原型方式。
class Person { constructor(name, hobby) { this.name = name; this.hobby = hobby; } introduce() { console.log(`你們好,個人名字叫:${this.name},我喜歡${this.hobby}。`); } } const devpoint = new Person("DevPoint", "coding"); devpoint.introduce();
附帶說明,introduce方法中的字符串稱爲模板字符串,它是使用反引號而不是引號建立的。這樣可使用美圓符號和大括號將表達式插入字符串。
與常規字符串拼接相比,模板字符串的好處是它能夠跨越多行:
const str = `line 1 line 2 line 3 `; console.log(str);
它被稱爲模板字符串,由於它對實現模板頗有用。
function pStr(text) { return `
${text}
`;
}
pStr("Hello world"); //
Hello world
一個類能夠從另外一個類繼承(重用現有類的代碼):
class Person { constructor(name, hobby) { this.name = name; this.hobby = hobby; } introduce() { console.log(`你們好,個人名字叫:${this.name},我喜歡${this.hobby}。`); } } class ProfessionalPerson extends Person { constructor(name, hobby, profession) { super(name, hobby); // 執行 Person 的構造函數 this.profession = profession; } introduce() { super.introduce(); // 調用 Person 類的方法 console.log(`個人職業是 ${this.profession}。`); } } const devpoint = new ProfessionalPerson("DevPoint", "coding", "程序員"); devpoint.introduce();
這裏使用extends關鍵字在兩個類之間建立繼承關係,其中Person爲父類。代碼中用了兩次super關鍵字,第一次是在構造函數中調用父類的構造函數,第二次,像使用對象同樣使用它來調用父類的introduce方法。super關鍵字的行爲會因使用的位置而異。
在構造函數中使用時,super關鍵字將單獨出現,而且必須在使用this關鍵字以前使用。以下代碼就是有異常的。
class ProfessionalPerson extends Person { constructor(name, hobby, profession) { this.profession = profession; // 這裏會出現異常 super(name, hobby); // 執行 Person 的構造函數 } introduce() { super.introduce(); // 調用 Person 類的方法 console.log(`個人職業是 ${this.profession}。`); } }
ES6新增了兩種數據結構:Map和Set
Map是鍵-值對的集合,而且可以記住鍵的原始插入順序。
const mapPerson = new Map(); mapPerson.set("name", "DevPoint"); mapPerson.set("profession", "Coding"); const myName = mapPerson.get("name"); console.log(myName); // DevPoint
Map對象可使用任何對象類型做爲鍵。看起來是不有點像Object,下面咱們能夠看看他們的比較:
Map | Object | |
---|---|---|
意外的鍵 | Map 默認狀況不包含任何鍵,只包含顯式插入的鍵。 | 一個 Object 有一個原型,原型鏈上的鍵名有可能和你本身在對象上的設置的鍵名產生衝突。 |
鍵的類型 | Map的鍵能夠是任意值,包括函數、對象或任意基本類型。 | 一個Object 的鍵必須是一個 String 或是Symbol。 |
鍵的順序 | Map 中的 key 是有序的。所以,當迭代的時候,一個 Map 對象以插入的順序返回鍵值。 | 一個 Object 的鍵是無序的 |
Size | Map 的鍵值對個數能夠輕易地經過size 屬性獲取 | Object 的鍵值對個數只能手動計算,須要本身構建方法 |
迭代 | Map 是 iterable 的,因此能夠直接被迭代。 | 迭代一個Object須要以某種方式獲取它的鍵而後才能迭代。 |
性能 | 在頻繁增刪鍵值對的場景下表現更好 | 在頻繁添加和刪除鍵值對的場景下未做出優化 |
Set對象就像一個數組,可是僅包含惟一項。Set對象是值的集合,能夠按照插入的順序迭代它的元素。Set中的元素只會出現一次,即 Set 中的元素是惟一的。
const numbers = new Set(); numbers.add(1); numbers.add(1); console.log(numbers); // Set { 1 }
儘管兩次add是一樣的值,程序自己不會出現任何異常,但該集合仍然只包含一項。
讓談談來學習一點更復雜的知識,WeakMap和WeakSet。它們分別是Map和Set的弱引用版本。
WeakMap其鍵必須是Object,而值能夠是任意的。
WeakSet 對象是一些對象值的集合, 而且其中的每一個對象值都只能出現一次,在WeakSet的集合中是惟一的。
它和 Set 對象的區別有兩點:
與Set相比,WeakSet 只能是對象的集合,而不能是任何類型的任意值。
WeakSet持弱引用:集合中對象的引用爲弱引用。 若是沒有其餘的對WeakSet中對象的引用,那麼這些對象會被當成垃圾回收掉。 這也意味着WeakSet中沒有存儲當前對象的列表。 正由於這樣,WeakSet 是不可枚舉的。
一旦再也不引用WeakMap的鍵,便會對其進行垃圾回收(由Javascript運行時從內存中刪除)。
let key1 = {}; const key2 = {}; const wm = new WeakMap(); wm.set(key1, 1); wm.set(key2, 2); key1 = null; // 取消引用
在key1被取消引用以後,它的對應值將被垃圾回收,意味着它將在將來的某個時間點消失。
一樣,若是將一個對象添加到WeakSet中,而後再取消引用它,它也將被垃圾回收。
let item1 = {}; const item2 = {}; const ws = new WeakSet(); ws.add(item1); ws.add(item2); item1 = null; // 取消引用
Promise 對象用於表示一個異步操做的最終完成 (或失敗)及其結果值。是ES6的一個經常使用功能,它是對傳統函數回調模式的改進。
一個 Promise 必然處於如下幾種狀態之一:
待定(pending): 初始狀態,既沒有被兌現,也沒有被拒絕。
已兌現(fulfilled): 意味着操做成功完成。
已拒絕(rejected): 意味着操做失敗。
例如,這是使用傳統回調的方式:
setTimeout(function () { const currentTime = new Date(); console.log(currentTime); }, 1000);
這是一個計時器,顯示一秒鐘後的時間。
這是一個使用相同setTimeout邏輯的Promise對象:
const afterOneSecond = new Promise(function (resolve, reject) { setTimeout(function () { const currentTime = new Date(); resolve(currentTime); }, 1000); });
它接受帶有兩個參數的函數:resolve和reject。這兩個都是當有返回值時能夠調用的函數。調用resolve函數返回一個值,能夠調用reject函數返回一個錯誤。
而後,可使用then語法將回調函數附加到這個afteronessecond對象上:
afterOneSecond.then((t) => console.log(t));
promise相對於傳統回調的好處是promise對象能夠被傳遞。所以,在設置promise以後,能夠自由地將它發送到其餘地方,以處理計時器解析後要作的事情。
另外一個很酷的事情是,promise能夠與多個then子句連接在一塊兒,即promise的鏈式調用。
afterOneSecond.then((t) => t.getTime()) .then((time) => console.log(time));
每一個then子句將其值做爲參數返回到下一個then子句。
http://www.ssnd.com.cn 化妝品OEM代加工
下面就來介紹在VUE中,比較實用的ES6的方法或屬性。
Object.assign() 方法用於將全部可枚舉屬性的值從一個或多個源對象分配到目標對象。它將返回目標對象。提供了一種簡單的方法來淺克隆現有對象。
const obj1 = { a: 1 } const obj2 = Object.assign({}, obj1)
構造並返回一個新字符串,該字符串包含被鏈接在一塊兒的指定數量的字符串的副本。
const str = "DevPoint ".repeat(3); console.log(str); // DevPoint DevPoint DevPoint
用來判斷當前字符串是否以另一個給定的子字符串開頭(區分大小寫),並根據判斷結果返回 true 或 false。
const str = "DevPoint".startsWith("D"); const str2 = "DevPoint".startsWith("d"); console.log(str); // true console.log(str2); // false
用來判斷當前字符串是不是以另一個給定的子字符串「結尾」的,根據判斷結果返回 true 或 false。
const str = "DevPoint".endsWith("t"); console.log(str); // true
用於判斷一個字符串是否包含在另外一個字符串中,根據狀況返回 true 或 false。
const str = "DevPoint".includes("P"); console.log(str); // true
返回數組中知足提供的過濾函數的 第一個元素的值,不然返回 undefined。
const arrNumbers = [5, 12, 8, 130, 44]; const foundNumbers = arrNumbers.find((number) => number > 10); console.log(foundNumbers); // 12是數組第一個大於10的數
這不是方法而是屬性,返回函數實例的名稱,每一個函數都有一個name屬性,該屬性提供字符串形式的函數名稱
setTimeout.name; // "setTimeout" const weather = () => { console.log("今每天氣真好!"); }; console.log(weather.name); // weather
ES6的新特徵,某種程度上表明的Javascript在將來的態度,這些新的特徵讓我火燒眉毛應用到項目中,不斷接受新挑戰,提高本身技能。