眾所周知,JavaScript作為弱類型語言,一直是精華與糟粕共存,許多“詭異”的地方我們不得不接受並使用。其實ES6(又稱ECMAScript 2015)在2015年6月就已經正式發布了,其中提出的很多新的特性讓JavaScript更加完善和豐富,對於前端開發者可謂一大福音。
目前各大瀏覽器的最新版本對ES6的支持度也越來越高,大部分的特性都實現了( ES6 支持 )。另外現在也有很多的轉換器(如Babel
),將ES6和ES7的代碼轉換為ES5的代碼,這就意味着我們現在就可以使用這些新特性應用到我們的項目中去。
本篇對ES6中的關於變量部分的新特性進行介紹,本系列傳送門:
- 1 變量部分
- 2 現有對象拓展
- 3 新增數據類型/數據結構
- 4 新的異步編程模式
- 5 類和模塊
1 利用let和const引入塊級作用域
以往JavaScript是不具有塊級作用域的,一個函數才能構成一個作用域,局部變量在整個函數內都是有定義的,舉個栗子
for(var i = 0;i < 10;i++){
}
console.log(i); //輸出10
最后在for循環之后,i變量僅用於for循環,但在卻被泄露成全局變量形成變量污染,這就是不合理的地方,通過ES6中定義的let
關鍵字可以形成僅作用於該塊作用域的局部變量,
//ES6環境下
for(let i = 0;i < 10;i++){
}
console.log(i); //輸出ReferenceError(未定義)
利用Babel將這段ES6代碼轉換為ES5代碼后,實際上是對ES5的代碼對其原理進行模擬達到一致的效果,因此可以幫助我們的理解:
//Babel轉換后
for (var _i = 0; _i < 10; _i++) {
}
console.log(i); //輸出ReferenceError(未定義)
可以看到,對於let聲明的局部變量,如果外部有相同定義,會通過添加下划線將其轉換為另外的變量,表達意思就是let將該變量僅在該塊作用域內可用。
再舉個栗子:
var a = [];
for (var i = 0; i < 3; i++) {
a[i] = function () {
console.log(i);
};
}
a[1](); //輸出3
a[2](); //輸出3
上面的代碼的三次循環中i始終為同一個變量,值最后為3。a數組中的函數讀到的i也是這個值,因此都是輸出3,這跟我們想要的結果並不一致。而利用let這個新特性可以很好的解決這個問題:
//ES6環境
var a = [];
for (let i = 0; i < 3; i++) {
a[i] = function () {
console.log(i);
};
}
a[1](); //輸出1
a[2](); //輸出2
//Babel轉換后
var a = [];
var _loop = function _loop(i) {
a[i] = function () {
console.log(i);
};
};
for (var i = 0; i < 3; i++) {
_loop(i);
}
a[1](); //輸出1
a[2](); //輸出2
這次轉換后稍微變得復雜了一些,實際上是新定義一個函數,將循環變量i作為參數傳進去,可以這樣理解ES6中代碼通過let將三次循環中的i固定於各自的塊作用域中,互不干擾。
另外關於let要注意的幾點:
console.log(a); //輸出ReferenceError(未定義),let聲明的變量不會變量提升,這也是規范我們的代碼先聲明后使用。
let a = 3;
let a = 4; //錯誤,let聲明的變量不能重復定義
總之,用let讓我們的代碼更加規范避免了很多問題,因此盡可能使用let代替var.
- 與
let
類似const
也能形成塊作用域,不同點在於const聲明的變量為常量,不可改變
舉個栗子:
if(true){
const MAX = 999;
MAX = 3; //報錯:"MAX" is read-only
}
console.log(MAX);//輸出ReferenceError(未定義)
可以看出const也形成塊級作用域,而且值不可改變,有一點要注意的是不能改變的是const類型變量存儲的東西,舉個栗子更好理解:
const person = {};
person.name = 'vicfeel'; //正確,person存儲的是指向該對象的地址,對象內容可以改變
person = {}; //報錯:"person" is read-only,該地址不能改變
2 變量解析與賦值
以往多個變量的賦值我們使用如下的方式:
var a = 1;
var b = 2;
var c = 3;
var d = 4,e = 5,f = 5;
ES6中增加一種更便捷的多變量賦值方法:
var [a,b,c] = [1,2,3];
系統會自動對數組內元素進行對應賦值,也就是說我們也可以用這種方式來進行變量的聲明:
//ES6環境下
var arr = [1,2,3];
var [a,b,c] = arr;
我們用Babel看一下是如何模擬的:
//Babel轉換后
var _ref = [1, 2,3];
var a = _ref[0];
var b = _ref[1];
var c = _ref[2];
可以看到是通過數組下標依次向后賦值,下面我對多種情況進行了賦值測試:
{
//數量不對應
let [a,b,c] = [1,2];
console.log(a); //1
console.log(b); //2
console.log(c); //undefined
//按照上面babel轉換的理解,c = _ref[2]不存在該要素因此c為undefined
}
{
//多層數組
let [a,[b,c],d] = [1,[2,3],4];
console.log(a); //1
console.log(b); //2
console.log(c); //3
console.log(d); //4
}
{
//多層不對應
let [a,[b,c],d] = [1,[2],3];
console.log(a); //1
console.log(b); //2
console.log(c); //undefined
console.log(d); //3
}
{
//對應值非數組
let [a,b,c] = 1; //報錯
let [a,b,c] = false; //報錯,等號右邊必須為可遍歷對象
}
了解映射的原理之后,一個很好的應用場景就是交換數值,現在可以這樣簡單的實現:
//ES6環境下
let [x,y] = [0,1];
[x,y] = [y,x];
- 除此之外,ES6還在映射賦值中加入了默認值
//ES6環境下
let [a, b = 2,c] = [1]; //y無對應值時,默認值則為2
console.log(a); //1
console.log(b); //2
console.log(c); //undefined
看一下ES5的模擬
//Babel轉換后
var _ref = [1];
var a = _ref[0];
var _ref$ = _ref[1];
var b = _ref$ === undefined ? 2 : _ref$; //通過‘===’嚴格等於判斷是否為undefined,是的話采用默認值
var c = _ref[2]; //所以是undefined
- 針對對象的映射賦值
直接看栗子:
//ES6環境下
var { oA, oB } = { oA: "a", oB: "b" };
console.log(oA); //"a"
console.log(oB); //"b"
看一下ES5的模擬
//Babel轉換后
var _oA$oB = { oA: "aaa", oB: "bbb" };
var oA = _oA$oB.oA; //原來是通過同名屬性進行對應
var oB = _oA$oB.oB;
console.log(oA);
console.log(oB);
了解了對應的原理之后,我們再做一下其它情況的測試:
{
//順序改變
var { oA, oB } = { oB: "a", oA: "b" };
console.log(oA); //"b"
console.log(oB); //"a"
}
{
//數量不對應
var { oA, oB } = { oA: "a"};
console.log(oA); //"a"
console.log(oB); //undefined,等號右邊對象找不到oB屬性
}
掌握這種方法,可以簡化很多之前操作,如獲取一個對象的某些屬性,可以通過以下方式:
//ES6環境下
var person = {
name:'Vicfeel',
age:'23',
sex:'Male'
}
let {name,age,sex} = person;
console.log(name);//Vicfeel
console.log(age); //23
console.log(sex); //Male
參考Reference
http://www.ecma-international.org/ecma-262/6.0/index.html
http://es6.ruanyifeng.com/
http://www.cnblogs.com/Wayou/p/es6_new_features.html
http://www.cnblogs.com/snandy/archive/2015/05/10/4485832.html
博文作者:vicfeel
博文出處:http://www.cnblogs.com/vicfeel
本文版權歸作者和博客園共有,歡迎轉載,但須保留此段聲明,並給出原文鏈接,謝謝合作!
如果閱讀了本文章,覺得有幫助,您可以為我的博文點擊“推薦一下”!