ES6標準以及頒佈兩年了,可是,好像尚未徹底走進咱們的平常開發。這篇文章從ES6的基本類型擴展入手,逐步展開對ES6的介紹。編程
JavaScript是由Netscape創造的,該公司1996年11月將JavaScript語言提交國際標準化組織ECMA。因而ECMA次年就發佈了ECMAScript 1.0版本。之因此不採用JavaScript命名,緣由有兩個,一個是版權問題,另外一個也是想經過ECMAScript代表制定者是ECMA而非Netscape。固然,這不是咱們關注的重點。數組
1998年,發佈了ECMAScript 2.0,1999年發佈了ECMAScript 3.0。這是ECMAScript自頒佈以來最廣爲支持的版本,咱們如今所使用的JavaScript語法和規定大部分都來源於這個版本。它是一個通用標準,奠基了JavaScript的基本語法。2000年後,4.0開始提上日程,可是因爲各方分歧很大,致使4.0草案流產,只在最後發佈了一個小的改進版本,即ES 3.1,不久後改名爲ECMAScript 5.0。函數
2011年,ECMAScript 5.1版發佈後,就開始制定6.0版了。2015年6月發佈了ES6的第一個版本,正式名稱就是《ECMAScript 2015標準》(簡稱 ES2015)。2016年6月,小幅修訂的《ECMAScript 2016標準》(簡稱 ES2016)如期發佈,這個版本能夠看做是 ES6.1 版,由於二者的差別很是小,基本上是同一個標準。根據計劃,2017年6月發佈 ES2017 標準。所以,ES6 既是一個歷史名詞,也是一個泛指,含義是5.1版之後的 JavaScript 的下一代標準,涵蓋了ES201五、ES201六、ES2017等等,而ES2015 則是正式名稱,特指該年發佈的正式版本的語言標準。編碼
在ES6以前,JavaScript的做用域只有兩種:全局做用域和函數做用域。而在這兩個做用域裏,存在一種奇怪的現象--變量提高。MDN上的介紹是 在編譯階段將變量和函數聲明放入內存中,但仍然保留在編碼中鍵入的位置。rest
function(){ console.log(a); var a= 'hello'; } function(){ var a = undefined; console.log(a); a= 'hello'; }
上面的兩段代碼是等價的,也說明了變量提高的本質。在函數做用域內,函數或者變量的聲明會被放到做用域頂部,而其餘操做仍然保留在原來的鍵入位置。code
ES6中引入塊級做用域的概念,和Java或者C語言中的局部變量做用域很像。所以,ES6中的塊級做用域存在如下特色:暫時性死區、不可重複命名、不存在變量提高。經過關鍵字let和const聲明的變量只在塊級做用域內有效。對象
{ let i = 1; } console.log(i);//Error
上面的代碼塊解釋了ES6中的塊級做用域的概念,一個{}即爲一個塊級做用域,做用域內的變量在做用域外沒法被訪問。ip
塊級做用域首先帶來的問題就是暫時性死區。從做用域開始到變量被聲明以前的空間內是該變量的死區,在這個空間內不能對該變量進行任何操做。例如:內存
{ //死區開始 i = 2;//Error console.log(i);//Error let i = 1;//死區結束 }
這個很容易理解,var聲明的變量能夠重複命名,後來的命名能夠把以前的覆蓋掉,可是let聲明的變量若是出現重複命名的狀況,會直接報錯。作用域
const用來聲明常量,一旦聲明,值就不可改變。所以,const一旦聲明,就必須當即初始化。這一點和Java或者C語言很像。
可是對於複合型變量,變量名不是指向數據,而是指向數據所在的地址。所以,const定義的複合型變量,只能保證變量名指向的地址不變,並不能確保改地址的內存儲的數據不變。
const foo = {}; foo.a = 1; foo = {}//Error const b = []; b.length = 1; b = [];//Error
上面的一段代碼中,分別用const聲明瞭一個對象和一個數組。咱們能夠給對象或者數組的一個屬性賦值,可是不能直接給對象或者數組總體賦值。
結構賦值是ES6引入的一種新的變量賦值方式, MDN上的解釋是:解構賦值語法是一個Javascript表達式,這使得能夠將值從數組或屬性從對象提取到不一樣的變量中。
let [a, b, c] = [1, 2, 3]; console.log(a,b,c);//1 2 3 let [foo, [[bar], baz]] = [1, [[2], 3]]; console.log(foo, bar, baz);//1 2 3
上面的代碼是兩種數組解構賦值,只要等號左邊的變量在右邊的數組中可以找到對應的位置,就能夠進行解構賦值。
對象的結構賦值和數組略有不一樣。let { key:name } = obj。等價於 let name = obj[key]。
let obj = { first: 'hello', second: 'world' }; let { first: f, second: s } = obj; console.log(f, s);//hello world console.log(first, second);//Error let { foo, bar } = { foo: "aaa", bar: "bbb" }; console.log(foo, bar);// aaa bbb let { bar, foo } = { foo: "aaa", bar: "bbb" }; console.log(foo, bar);// aaa bbb
後兩段代碼是對象屬性名和值相同時的簡潔寫法。從後兩段代碼咱們能夠了解到對象解構賦值的本質:先在對象內部找到和變量名相同的屬性,而後再把屬性值賦給變量。對象的解構賦值自己是一次變量賦值運算。
解構賦值也能夠設置默認值,當結構失敗時,直接取默認值。例如:
var {x = 3} = {}; console.log(x); //3 var {x, y = 5} = {x: 1}; console.log(x, y) // 1 5
[x, y] = [y, x];
[x, y] = func();
let a={x:1,y:2,z:3,w:4}; let {x,y}=a; let b={x,y};
import {getOS} from '../utils';
ES6中爲函數加入了添加默認值的功能。
function log(x, y = 'World') { console.log(x, y); } log('Hello');//Hello World
下邊的代碼有點意思,是函數解構參數的默認值寫法。
// 寫法一 function m1({x = 0, y = 0} = {}) { return [x, y]; } // 寫法二 function m2({x, y} = { x: 0, y: 0 }) { return [x, y]; } m1({x: 3}); m2({x: 3});
兩種寫法略有不一樣,所表達的意思也不同。首先,函數的解構參數的寫法是這樣的:
function add({x, y}){ return x + y; }
固然,這裏也能夠是數組解構,上面的代碼拿對象解構作事例。
寫法一,兩個大括號相等,表達的意思是函數參數擁有默認值,當m1函數被調用時沒有傳遞參數時,區默認值即{}。以後,進行解構賦值。方法一里的解構賦值是帶有默認值的解構賦值,所以,當解構失敗時,x和y分別取默認值0。因此m1({x: 3})的執行結果是[3,0]。
寫法二,兩個大括號相等,一樣表達的意思是函數參數擁有默認值,當m2函數被調用時沒有傳遞參數時,區默認值即{ x: 0, y: 0}。方法二里的解構賦值沒有默認值,所以,當解構失敗時,x和y的值都是undefined。因此,m2()的值是[0,0],可是m2({x: 3})的則是[3,undefined]。
函數的解構參數最大的意義在於,我能夠不用關心傳遞過來的數組或者對象內部的解構,只要內部有我想要的屬性值就夠了,這樣在必定程度上下降了邏輯函數之間的耦合。例如:
let obj = { name: 'hello', age: 18, address: 'BeiJing', mobile: '123123123', timestamp: '1496940548319' } function getName({name}){ return name; } getName(obj);
ES6爲函數參數引入rest寫法。也就是咱們偶爾會在ES6代碼裏見到的 ...
function add(...values) { let sum = 0; for (let val of values) { sum += val; } return sum; }
rest參數用於獲取函數的多餘參數,相似於arguments對象。與之不一樣的是,rest參數是一個數組,也就意味着咱們能夠對rest參數使用數組的全部方法。
ES6的函數擴展裏,最引人注意的應該就是箭頭函數了。一個最簡單的箭頭函數:let f = v => v
等價於
let f = function(v){ return v }
當箭頭函數沒有參數或者有多個參數時,使用圓括號把參數括起來。當箭頭函數的函數體多於一行代碼時,就採用花括號把函數體括起來,並使用return語句返回值。
箭頭函數的出現,主要是爲了簡化函數的書寫。對於開發而言,最大的好處是簡單易讀,同時匿名函數寫起來也更加舒服天然。
ES6的基本擴展還有一些沒有在這裏詳細介紹。整體感受,ES6作了一些語法的豐富,使得JavaScript寫起來更加舒服了,特別是結構賦值和箭頭函數的引入,用習慣了之後,徹底是另一種編程體驗。