2015年6月,ES6正式發布。至今一年多的時間內,各個瀏覽器也對支持ES6做出了很大的改善,所以同學們無需顧忌你寫代碼的瀏覽器不認識~
這么久的東西一定早有大神剖析過,今天我們以一個后端菜鳥的視角重新解讀下ES6加入的新語法。
首先很開心,ES6對class(類)的支持上升到了一個新高度,允許構造和繼承,新語法看上來是這樣的:
//繼承 class parent { constructor(par) { this.Name = par; console.log('[父類的構造方法 ' + this.Name + ']'); } sayHello() { console.log('父類的sayHello方法 Hello ' + this.Name); } } class child extends parent { constructor(name) { super('[子類調用父類的構造 ' + name + ']'); } sayGoodBye() { console.log('子類的sayGoobBue方法 GoodBye ' + this.Name); } }
//調用
var a = new parent('Es6');
a.sayHello();
var b = new child('Max');
b.sayHello();
b.sayGoodByr();
有沒有被驚艷到?(可這的確是個Js文件),運行后的效果是這樣的:
和后端一樣,子類繼承父類需要使用關鍵字extends,繼承后,可以使用關鍵字super調用父類屬性。
並且我發現此處的this在被繼承后也被子類一並帶入,也就是說:this的作用域將會被向下傳遞。(請參照運行結果最后一行。)
上面是class(類)的繼承,有了繼承,我們在構建Js代碼時,就會獲得更強大的能力(可擴展、易維護、易閱讀等)。
可能有些同學會說了:我根本不習慣這樣寫,感覺都不像Js了啊喂!
沒關系,ES6怎么會忘記我們的對象字面量呢?繼承當然也會出現在對象字面量的應用中:
var Es6Parent = { cons(mess) { console.log('原型Es6Parent的cons方法' + mess); } } var Es6Child = { //設置原型為 Es6Parent ,相當於繼承 __proto__: Es6Parent, work() { console.log('下層Es6Child的work方法 I\'m very busy!'); } }
//調用
Es6Parent.cons('原型cons方法');
Es6Child.cons('下級調用上層原型的方法');
Es6Child.work();
運行結果如下:
設置的方式也超簡單:使用關鍵字'__proto__'設置原型即可(只不過是給原型鏈換了種叫法而已嘛)
下面介紹一些簡單實用的語法糖,首先是方便的參數設置:
var Name = 'Max'; console.log(`我是很方便帶參數的的波浪符${Name}`);
重點是${},它可以直接在字符串中帶入參數(拼接方便很多有木有),但是需要和波浪符(`)搭配使用才有效哦~
接下來是...語法,當它出現在形參列表內,代表不定量參數:
function show(...all) { all.forEach(function (i, v) { console.log(`不定量參數的值:${v}`); }, all); }
//調用
show(1,2,3,4,5,6);
運行結果如下:
定義的時候是不是省力很多呢?還有更好用的,當...出現在實參列表內,它將允許直接傳入數組(而不是使用apply):
function sayHi(name, age, sex) { console.log(`大家好,我是${name},今年${age}歲,我是${sex}生。`); } //調用 var arr = ['小明', 18, '男']; sayHi(...arr);
運行結果如下:
定義sayHi函數時,寫了3個參數,調用時使用...傳入數組時,它將從0下標開始依次順序匹配參數。
我們在工作中,經常使用回調函數來完成某些操作,但是每次回調都要寫個完整的funciton(好麻煩的說),ES6引入了lambda表達式,大大優化了這一操作:
function callBack(back) { back(); } //兩種調用方式對比 callBack(function () { console.log('我是舊的調用方式'); }); callBack(()=>console.log('我是lambda調用方式'));
運行結果如下:
使用了lambda以后的函數傳入方式是不是更優雅呢?如果比較萌比,那就再來一個對象字面量版本的:
var show_msg = (name, job) => { console.log(`大家好,我叫${name},是一名${job}`) }; //調用 show_msg('暮城','軟件攻城獅');
運行結果如下:
現在大家應該已經很清楚了:()=>語法呢,=>前面是參數列表,后面是方法體。以后看到類似的語法可別暈~
語法糖還有很多,我先說這么多,因為下面要說更重要的:新數據類型和監聽的實現。
Es6新增了map,set,以及weakMap、weakSet四種類型。
它們都有什么差異呢?先說說map:map以key-value的方式存儲,並且在map內所有的鍵都是唯一的,來看被for in 遍歷后的結果:
var par1 = 'key_1'; var par2 = 'key_2'; var testMap = new Map(); testMap.set(par1, '第一個值'); testMap.set(par2, '第二個值'); testMap.set(par1, '第三個值'); for(i of testMap) { console.log(i); }
可以看到第三個值將第一個值頂替掉而不是共存,原因就是第一個值和第三個值鍵相同。
set和map的差別就在於,它是以value的方式存儲,而且同樣不允許重復值出現:
var par11 = 'value_1'; var par22 = 'value_2'; var testSet = new Set(); testSet.add(par11); testSet.add(par22); testSet.add(par11); for(i of testSet) { console.log(i); }
至於WeakMap和WeakSet,使用方式都一樣,只是這兩種類型的鍵都采用了弱引用,即:作為屬性鍵的對象如果沒有其他地方引用時自動回收(自動釋放)。
此處就不多做解釋,不過我推薦大家使用WeakMap和WeakSet。
現在,我們終於說到了監聽器(監聽器可是重頭戲)
監聽器是很有意思的東西,它給予了我們極大的便利,這一點在實現MVVM模型的操作時尤為重要,ES6中的監聽看上去大概是這樣的:
//被監聽的對象 var ob = { name: 'Max', like: 'women' }; //觸發監聽時的程序 var pro = { set: function (cagObj, cagKey, cagValue) { console.log(`${cagObj[cagKey]}變為了${cagValue}`); cagObj[cagKey] = cagValue; } } ob = new Proxy(ob, pro); ob.like = 'man';
set內定義的function將會在監聽對象發生改變時自動觸發,參數列表內的3個值也是默認定義的,它們依次是:被修改的對象、該對象的鍵、該對象的值。
需要注意的是如果你為某元素設定的監聽器觸發后,它原本的修改進程會被阻止(如果你不進行這一步的話),所以需要我們顯式的去修改才可。
運行效果如下:
擁有了這些特性,我們自己想寫一個類似於VUE的數據框架也變得簡單了許多。
另外,ES6還更新了很多命名空間下的函數(如:math),這里就不一一羅列(寫不完並且網上大把)。
最后,ES6的推出讓我直觀感覺到前后端差距進一步縮小,希望有一天Js可以不借助后端完成數據交互~(不要吐槽我學的晚)