
ES6給JS世界帶來的變化是巨大的,與以往“小打小鬧”對比起來,這次的語法糖是真的甜。這次我就結(jié)合平時的工作情況,把一些我認為真正解決了開發(fā)者痛點的語法糖一一挪列出來。有什么不足,請評論處指正。
Features
for-of 數(shù)組遍歷
var a = ["a","b","c","d","e"];
for(var idx in a){
console.log( idx );
}
// 0 1 2 3 4 索引值
for(var val of a){
console.log( val );
}
// "a" "b" "c" "d" "e" 內(nèi)容
for (var c of "hello") {
console.log( c );
}
// "h" "e" "l" "l" "o"
for({x:o.a} of [{x:1},{x:2},{x:3}]){
console.log( o.a );
}
// 1 2 3
- 這是最簡潔、最直接的遍歷數(shù)組元素的語法
- 這個方法避開了for-in循環(huán)的所有缺陷
- 與forEach()不同的是,它可以正確響應break、continue和return語句
Arrow Function 函數(shù)表達式
先從JavaScript箭頭符號說起。
“趨向于“運算符是什么?<!-- 又是什么?
看個例子就明白了。
<!-- 我是被完美的注釋掉了
var a = 2;
while(a --> 0){
console.log(a);
}
//0,1
實際上JavaScript從語言誕生之日起就已經(jīng)把箭頭符號利用上了,下表做了一個大致的統(tǒng)計
| 符號 | 作用 |
|---|---|
| >> | 位運算 |
| <!-- | 單行注釋 |
| --> | "趨向于"運算符 |
| <= | 小于等于 |
| => | 這是什么鬼? |
先來看看=>在代碼中大概長什么樣?
var f2 = x=>x*2;
var f3 = (x,y) => {
var z = x*2+y;
y ++;
x *= 3;
return (x+y+z)/2;
};
這樣的寫法是不是比以前傳統(tǒng)函數(shù)寫法簡潔得多?簡單來說,(var1,var2...) => {Function Body} 這樣的函數(shù)表達式,我們通常稱之為Lambda表達式
All the capabilities of normal function parameters are available to arrow functions, including default values, destructuring, rest parameters, etc.(所有普通函數(shù)參數(shù)所包含的能力,包括默認值設置、重構、冗余等等都適用于箭頭函數(shù))
然而不僅僅如此
再來看一段代碼
var controller = {
makeRequest: function(..) {
var self = this;
btn.addEventListener( "click", function(){
// ..
self.makeRequest(..);
}, false );
}
};
這是傳統(tǒng)的做法,在btn點擊事件回調(diào)方法中用的this和外面的this不一樣,為了保留上下文中的this變量,將this賦值給了self。相信這種問題在開發(fā)的過程中大多數(shù)人都已遇到無數(shù)次了。來看看Lambda函數(shù)表達式怎么做?
var controller = {
makeRequest: function(..) {
btn.addEventListener( "click", () => {
// ..
this.makeRequest(..); }, false );
}
};
自從有了Lambda,我的代碼少了幾百行!!
Lambda雖好,可不能濫用
來看一段代碼
var controller ={
makeFunction:function(){
console.log(this);
this.helper();
},
makeLambda : () => {
console.log(this);
this.helper();
},
helper : () => {
console.log('ok!!!')
}
};
controller.makeFunction();//[object Object] ok!!!
controller.makeLambda();//reference fails
引用《You Don't Know JS ES6》書中解釋是
because this here doesn’t point to controller as it normally would. Where does it point? It lexically inherits this from the surrounding scope. In this previous snippet, that’s the global scope, where this points to the global object. Ugh.(這個this并沒有如我們預想的那樣指向controller,那么指向哪了呢?語義上從環(huán)境范圍中繼承了this對象。在之前的代碼片段中,就是全局范圍,也就是全局對象)
我補充一句,在瀏覽器環(huán)境下就是Window對象。另外再看一個栗子。
var controller ={
makeFunction:function(a,b){
console.log("Function arguments object:" +arguments[0]);
},
makeLambda : (a,b) => {
console.log("Lambda arguments object:" +arguments[0]);
},
foo : function(i){
// foo's implicit arguments binding
var f = (i) => arguments[0]+i;
return f(2);
}
};
controller.makeFunction(1,2);//Function arguments object:1
controller.makeLambda(1,2);//Lambda arguments object:undefined
console.log(controller.foo(1));//3
貌似都在說明,不管是this還是arguments對象都只能在閉包環(huán)境下才能正常使用。除此之外,如果想用lambda函數(shù)當做“Object Method”,首先還得確定該函數(shù)是否對自己有所引用亦或者用到了arguments參數(shù),否則請謹慎使用;
Block-Scoped Declarations & let&const 塊級作用域
JavaScript和Java的關系,正如雷鋒與雷峰塔的關系一樣。
說這些,無非就是想跟Java套套近乎。一直以來,JS中無塊級作用域一直為人所詬病。不僅僅是Java程序員,包括C系所有語言等開發(fā)者都不能理解。舉個栗子。
(function doSth(){
var a=1;
for(var i=0;i<2;i++){
var a=2;
console.log(a);//2
}
console.log(a);//2
})();
在for語句塊內(nèi)聲明的變量覆蓋了外層變量。ES6為了兼容,并沒有完全顛覆之前的var聲明,而是推出了新的聲明標識符let,把for循環(huán)中var改成let就可以了
(function doSth(){
var a=1;
for(var i=0;i<2;i++){
let a=2;
console.log(a);//2
}
console.log(a);//2
})();
另外一個const關鍵字,定義常量,除此之外,它和let的作用幾乎是一樣的。
Destructuring & default 解構與默認值
解構實際上是一種全新的賦值形式,相比以往更加靈活,代碼量更是少少少?。?!大概就是這樣的。
function foo() {
return [1,2,3];
}
//傳統(tǒng)做法
var tmp = foo(),
a = tmp[0], b = tmp[1], c = tmp[2];
//解構賦值
var[a,b,c] = foo();
var [,,c] = foo();//可以留空
var [a,...c] = foo();//可以通過不定參數(shù)指定最尾元素
//對象解構
var { foo, bar } = { foo: "dbs", bar: "asd" };
console.log(foo);// "dbs"
console.log(bar);// "asd
//解構參數(shù)
function foo({x,y}){
console.log( x, y );
}
foo( { y: 1, x: 2 } );// 2 1
foo( { y: 42 } );// undefined 42
foo( {} );// undefined undefined
不得不說,解構(Destructuring)是可以支持任意嵌套(Nested)的!另外就是默認值(Default)了,這又是一個代碼精簡的利器。
function foo() {
return [1,2,3];
}
var [a=3,b=6,c=9,d=12] = foo();
console.log( a, b, c, d ); // 1 2 3 12
//參數(shù)解構及默認值混合用法
function f6({x=10}={},{y}={y:10}){
console.log( x, y );
}
f6(); // 10 10
這塊就介紹到這,平時多用用就熟了。
Spread & Rest 分散與聚合
根據(jù)用法的理解,暫時翻譯為分散和聚合。
ES6也為此擴展了一個新的標識符...。我們繼續(xù)用代碼來看看怎么用吧。
function foo(x,y,z) {
console.log( x, y, z );
}
//invoke function 的時候
foo( ...[1,2,3] ); // 1 2 3
//等價于ES6之前Apply的用法
foo.apply( null, [1,2,3] ); // 1 2 3
//上下文環(huán)境可以是數(shù)組內(nèi)
var a = [2,3,4];
var b = [1,...a,5];
console.log( b ); // [1,2,3,4,5]
當...用在一個數(shù)組(其實對象也可以)前面,它可以表現(xiàn)為將數(shù)組中的值遍歷到對應的獨立的位置上。是為分散。
function foo(x, y, ...z) {
console.log( x, y, z );
}
foo( 1, 2, 3, 4, 5 ); // 1 2 [3,4,5]
這種用法就是把分散的值合并成為一個數(shù)組,是為聚合。
Template Literals 模板字符串
學過C語言第一次寫Hello的時候,就已經(jīng)用到了這個功能,那么今天,ES6終于把這個收入囊中。
function upper(s) {
return s.toUpperCase();
}
var who = "reader"
var text = `A very ${upper( "warm" )} welcome to all of you ${upper( `${who}s` )}!`;
console.log( text );
// A very WARM welcome to all of you READERS!
能理解上面的,基本就不用我繼續(xù)解釋了。
這篇文章先介紹到這里,ES6的新特性還遠遠不止這些。下篇會從代碼組織的角度來更進一步介紹。。