ES6帶來了Javascript新的變化,新的語法特性,使得之以前版本中需要特性方式才能解決的問題一些問題得到了簡化和支持,很大程度上提高了開發(fā)效率,擴展了Javascript功能呢。
1. let/const
ES6中增加了兩個新的變量聲明let和const。ES6之前Javascript是沒有明確的塊級作用域,{}代碼塊并不能作為一個完整的作用域來使用(當然函數(shù)存在其作用域),使用var聲明的變量在外部也可以引用
{
va a = 1;
}
console.log(a); // 1
let和const的引入使得我們可以產生局部的作用域
{
let a = 1;
console.log('inner:a=' + a); // inner:a=1
}
console.log('outer:a=' + a); // Reference Error
let和const存在以下的特性
- 必須要先聲明后使用,Javascript不會將
let/const聲明的變量進行提升,因此也不能使用typeof的值是否是undefined來判斷變量是否已經聲明。- 在作用域范圍內,不能重復聲明相同的變量名
// 變量聲明無法提前
{
console.log(a); // ReferenceError
// typeof a === 'undefined' // ReferenceError
let a = 1;
}
// 同名變量只能聲明一次
{
let a = 1;
let a = 2; // SyntaxError: Identifier 'a' has already been declared
}
let和const聲明的區(qū)別在于,const通常選擇對常量進行修飾,其自帶類似Java中final的效果,一旦聲明以后變量的引用不能發(fā)生變化,變量引用的內容本身可以發(fā)生變化
// 聲明一個數(shù)字字面量
const a = 1;
a = 2; // TypeError: Assignment to constant variable.
// 聲明一個對象的引用
const a = {};
a.a = 1; // 可以正常運行
2. 分離/剩余操作符
ES6引入了分離/剩余...,它有兩個用途:
- 在對變量賦值的時候可以用來對
Javascript中iterable的對象或者iterator進行展開- 在方法聲明中變量中使用,可以用來接受剩余參數(shù)
// 用于展開
var a = 'abcdef';
var b = [...a];
console.log(b); // [a,b,c,d,e,f]
// 可以使用展開效果替代數(shù)組的concat
var arr1 = [1,2,3];
var arr2 = [4,5,6];
var res = [...arr1, ...arr2]; // [1,2,3,4,5,6];
// 用與函數(shù)接受剩余參數(shù)
function f(a, ...b) {
console.log(a);
console.log(b);
}
f(1,2,3,4,5); // 1, [2,3,4,5]
3. 函數(shù)默認值
ES6中函數(shù)聲明時可以給形參添加默認值,以替代在函數(shù)體中對參數(shù)進行默認值設定的方式
// ES6之前
function f(a) {
var tempA = a || 'test'; // 設置默認值
console.log('a:'+a);
}
f(); // a:test
// ES6
function f(a='test'){
console.log('a:'+a);
}
f(); // a: test
默認值的設置除了使用字面量,也可以使用表達式,但是使用表達式需要注意表達式中變量的作用域和順序
function f(a=b, b=1) {
console.log(a,b);
}
f(); // ReferenceError: b is not defined
// 另一種情況
var b = 2;
function f(a=b, b=1) { // 因為形參中存在b,所以這里的a不能正確賦值
console.log(a,b);
}
f(); // ReferenceError: b is not defined
使用展開/剩余操作符的形參無法使用這種方式設置默認值
function f(...a = [1,2,3]) {} // SyntaxError: Unexpected token =
4. 對象解構
ES6中的數(shù)組和對象,增加了解構的方式來對其進行拆分,將對象或數(shù)組的值賦值給某個變量,省略掉中間變量,簡化取值寫法
// 對數(shù)組解構
var [a,b] = [1,2,3,4];
console.log(a); // 1
console.log(b); // 2
// 對對象解構
var {x: vx, y: vy} = {x:1, y: 2};
console.log(vx); // 1;
console.log(vy); // 2;
console.log(x); // ReferenceError
console.log(y); // ReferenceError
其中對于對象的解構需要注意,其中x: vx的意思是,聲明一個變量vx,并將對象中x的值賦值給變量vx,也就是說:左側是指向對象中的屬性,:右側是聲明的新的變量,即我們希望賦予的結果,也就是source: target結構
當然如果對象中屬新名和我們希望聲明的變量名一致,我們可以使用簡寫
var {x, y} = {x: 1, y: 2}; // 相當于{x: x, y: y} = {x: 1, y: 2};
解構對象如果不存在某屬性,那么賦值變量的值就為undefined
var {x, y, z} = {x: 1, y: 2};
console.log(z); // undefined
解構的過程可以使用剩余表達式,也可以設置默認值
// 可以和剩余表達式結合
var [a,...b] = [1,2,3,4];
console.log(a); // 1
console.log(b); // [2,3,4];
// 設置解構默認值
var {x , y: y=2} = {x: 1}; // 可以簡寫為 var {x, y=2} = {x:1}
console.log(y); // 2
// 省略中間變量交換變量的值
var x = 1;
var y = 2;
[x, y] = [y, x];
console.log(x); // 2
console.log(y); // 1
5. 字面量簡寫
ES6中創(chuàng)建對象的時候,可以使用屬性和方法有一種簡寫的方式
var x = 1;
// ES6之前寫法
var o = {
x: x,
f: function() {}
}
// ES6提供簡寫
var o = {
x, // 相當于 x: x
f() {} // 將:function直接省略
};
6. 計算屬性名
ES6之前如果屬性名是一個變量,我們很難通過一般的手段給對象增加變量屬性(應該只能通過Object.defineProperty定義屬性),ES6中增加了[]的語法來滿足需求
var x = 'vx';
var o = {
[x]: 1,
[x+ 'f']() {}
}
console.log(o); // {vx: 1, vxf: function}
7. 原型對象關聯(lián)
ES6新增Object.setPrototypeOf(target, source)方法來進行對象的原型對象__proto__的關聯(lián)操作
// ES6之前
var o1 = {};
var o2 = {
__proto__: o1
}
// ES6
Object.setPrototypeOf(o2, o1);
如果對象中使用了方法簡寫聲明,可以使用super參數(shù)來獲取該對象的原型對象
var o1 = {
f() { console.log('o1'); }
}
var o2 = {
f() {
super.f();
console.log('o2');
}
}
Object.setPrototypeOf(o2, o1);
o2.f(); // o1, o2
8. 模板語法
ES6使用模板語法,可以替代字符串拼接的方式來構建含有變量的字符串。模板語法使用了反引號作為標志,使用${}的插值方式獲取變量引用
// ES6之前只能使用+號進行字符串拼接
var name = 'patrick';
console.log('Hi, ' + name + ' welcome!');
// ES6之后使用模板語法
console.log(`Hi, ${name} welcome!`);
同時相比于字符串拼接,模板語法可以使用多行的寫法,而字符串拼接不可以
var name = 'patrick';
console.log(`Hi, ${name}
welcome`);
模板語法除此以外還有一個比較有意思的用途,我們可以定義一個特殊的函數(shù),來獲取模板語法中的不可變部分和插值部分
var name = 'patrick';
function f(strings, ...values){
console.log(strings);
console.log(values);
}
f`Hi, ${name} welcome` // ["Hi, ", " welcome", raw: Array(2)], ['patrick']
其中strings中存在一個屬性raw,其表示的是原本的字符串內容,相當于String.raw的結果
console.log('Hello, \r\n patrick welcome');
console.log(String.raw`Hello, \r\n patrick welcome`);
9. 箭頭函數(shù)
ES6的箭頭函數(shù)簡化了匿名函數(shù)的寫法,箭頭函數(shù)由三部分組成:參數(shù),箭頭,函數(shù)體。在函數(shù)體部分,如果不使用{}則會將表達式結果作為匿名函數(shù)返回值,使用{}可以支持多行語句
function f(callback) {
var v = callback();
console.log('v:' + v);
}
f(() => 1);
f(() => {
console.log('callback');
return 1;
})
如果在對象方法屬性中使用了箭頭函數(shù),且在箭頭函數(shù)中使用了this關鍵字,則需要注意this關鍵字的作用域上下文。
var a = 'outer';
var o = {
a: 'inner',
f: () => {
console.log(this.a);
}
}
o.f(); // outer
o.f.apply({a: 'apply'}); // outer
10. for of 循環(huán)
ES6中增加了for of循環(huán)來對所有的iteratable對象(對象中有[Symbol.iterator]屬性)進行遍歷,其中內置對象中String, Array, Generator,Collections/TypedArray已經實現(xiàn)了[Symbol.iterator]屬性,可直接遍歷
for(let s of 'abc') {
console.log(s); // a b c
}
11. 正則表達式
ES6中增加了兩個新的正則表達式標志符,使用u來擴展字符串中unicode字符的匹配,使用y來擴展處理匹配位置(操作reg.lastIndex來實現(xiàn)),并提供了reg.flags來獲取正則表達式使用到的修飾符。
12. 數(shù)字字面量
ES6中對八進制的數(shù)字字面量提供了0o的方式,替代了以前八進制的寫法0
console.log(0o17); // 15
13. Unicode處理
ES6中對于BMP(0x0000 -> 0xFFFF)以外的Unicode提供了新的支持方式\u{},并在對含有unicode字符串進行長度判斷時,要注意unicode字符所占有長度可能會帶來的問題
14. Symbol
ES6新的基本類型symbol,可以用來定義常量取代代碼中的Magic Number。通過Symbol(str)創(chuàng)建,也可以通過Symbol.for(str)創(chuàng)建,兩者區(qū)別在于后者會去查找是否已經使用Symbol.for創(chuàng)建相同key的symbol對象,已經創(chuàng)建則返回改symbol,否則創(chuàng)建新的symbol對象
var s1 = Symbol('key');
var s2 = Symbol('key');
var s3 = Symbol.for('key');
var s4 = Symbol.for('key');
console.log(s1 === s2); // false;
console.log(s1 === s3); // false
console.log(s3 === s4); // true
可以通過Symbol.keyFor()的方法獲取到使用Symbol.for創(chuàng)建的Symbol所使用的字符串key
var key = Symbol.keyFor(Symbol.for('my key'));
console.log(key); // my key
參考:
《你不知道的Javascript(ES6&Beyond)》