ES6的新特性(一)

函數(shù)默認值

特性 & 語法

// Before
function decimal(num, fix) {
    fix = fix === void(0) ? 2 : fix;

    return +num.toFixed(fix);
}
// After
function decimal(num, fix = 2) {
    return +num.toFixed(fix);
}

首先,我們看一下之前我們是怎么寫函數(shù)默認值的:我們通常會使用三元運算符來判斷入?yún)⑹欠裼兄担缓鬀Q定是否使用默認值運行函數(shù)(如示例中 fix = fix === void(0) ? 2 : fix)

而在 ES6 中,我們可以直接在函數(shù)的顯示入?yún)⒅兄付ê瘮?shù)默認值(function decimal(num, fix = 2){}),很明顯,這種寫法更自然易懂,也更加方便,不過有一點需要注意:

設(shè)定了默認值的入?yún)ⅲ瑧?yīng)該放在沒有設(shè)置默認值的參數(shù)之后,也就是我們不應(yīng)該這樣寫:function decimal(fix = 2, num){},雖然通過變通手段也可以正常運行,但不符合規(guī)范。

模板字符串

特性 & 語法

// Before
// Before.1
var type = 'simple';
'This is a ' + type + ' string join.'

// Before.2
var type = 'multiline';
'This \nis \na \n' + type + '\nstring.'

// Before.3
var type = 'pretty singleline';
'This \
is \
a \
' + type + '\
string.'
// OR
// Before.4
'This ' +
'is' +
'a' +
type +
'string.'
// After
var type = 'singleline';
`This is a ${type} string.`

var type = 'multiline';
`This
is
a
${type}
string.`

var type = 'pretty singleline';
`This \
is \
a \
${type} \
string.`

我們之前在對字符串和變量進行拼接的時候,通常都是反復一段一段使用引號包裹的字符串,再反復使用加號進行拼接(Before.1)。多行字符串的時候我們還要寫上蹩腳的 \n 來換行以得到一個多行的字符串(Before.2)。

在字符串過長的時候可能會使用 \ 在編輯器中書寫多行字符串來表示單行字符串,用來方便較長的字符串在編輯器中的閱讀(Before.3),或者簡單粗暴的反復引號加號這樣多行拼接(Before.4)。

ES6 中我們可以使用反引號(`,位于 TAB 上方)來輸入一段簡單明了的多行字符串,還可以在字符串中通過 ${變量名} 的形式方便地插入一個變量,是不是方便多了!

解構(gòu)賦值

數(shù)組解構(gòu)

var [a, ,b] = [1, 2, 3, 4, 5];
console.log(a); // => 1
console.log(b); // => 3

數(shù)組解構(gòu),使用變量聲明關(guān)鍵字聲明一個形參數(shù)組([a, , b]),等號后跟一個待解構(gòu)目標數(shù)組([1, 2, 3]),解構(gòu)時可以通過留空的方式跳過數(shù)組中間的個別元素,但是在形參數(shù)組中必須留有相應(yīng)空位才可以繼續(xù)解構(gòu)之后的元素,如果要跳過的元素處于數(shù)組末端,則在形參數(shù)組中可以不予留空。

對象解構(gòu)

var {b, c} = {a: 1, b: 2, c: 3};
console.log(b); // => 2
console.log(c); // => 3

對象解構(gòu)與數(shù)組解構(gòu)大體相同,不過需要注意一點

形參對象({b, c})的屬性或方法名必須與待解構(gòu)的目標對象中的屬性或方法名完全相同才能解構(gòu)到對應(yīng)的屬性或方法

對象匹配解構(gòu)

var example = function() {
    return {a: 1, b: 2, c: 3};
}
var {a: d, b: e, c: f} = example();
console.log(d, e, f); // => 1, 2, 3

對象匹配解構(gòu)是對象解構(gòu)的一種延伸用法,我們可以在形參對象中使用:來更改解構(gòu)后的變量名。

函數(shù)入?yún)⒔鈽?gòu)

function example({param: value}) {
    return value;
}
console.log(example({param: 5})); // => 5

函數(shù)的入?yún)⒔鈽?gòu)也是對象解構(gòu)的一種延伸用法,我們可以通過改寫入?yún)ο竽繕酥禐樽兞棵姆绞剑诤瘮?shù)內(nèi)部直接獲取到入?yún)ο笾心硞€屬性或方法的值。

函數(shù)入?yún)⒛J值解構(gòu)

function example({x, y, z = 0}) {
    return x + y + z;
}
console.log(example({x: 1, y: 2}));       // => 3
console.log(example({x: 1, y: 2, z: 3})); // => 6

這是入?yún)⒔鈽?gòu)的另一種用法,我們可以在入?yún)ο蟮男螀傩曰蚍椒ㄖ惺褂玫忍柕姆绞浇o入?yún)ο蟮哪承傩曰蚍椒ㄔO(shè)定默認值。

Let & Const

Let

無變量提升
// Before
console.log(num); // => undefined
var num = 1;
// After
console.log(num); // => ReferenceError
let num = 1;

使用 var 聲明的變量會自動提升到當前作用域的頂部,如果聲明位置與作用域頂部之間有另一個同名變量,很容易引起難以預知的錯誤。使用 let 聲明的變量則不會進行變成提升,規(guī)避了這個隱患。

注意:var 聲明的變量提升后雖然在聲明語句之前輸出為 undefined,但這并不代表 num 變量還沒有被聲明,此時 num 變量已經(jīng)完成聲明并分配了相應(yīng)內(nèi)存,只不過該變量目前的值為 undefined,并不是我們聲明語句中賦的初始值 1。

有塊級作用域

// Before
{
    var num = 1;

    console.log(num); // => 1
}
console.log(num);     // => 1
// After
{
    let num = 1;
    
    console.log(num); // => 1
}
console.log(num);     // => ReferenceError
  let 聲明的變量只能在當前塊級作用域中使用,最常見的應(yīng)用大概就是 for(let i = 0, i < 10; i++) {},相信許多小伙伴在面試題中見過。

禁止重復聲明
// Before
var dev = true;
var dev = false;

console.log(dev); // => false
// After
let dev = true;
let dev = false; // => SyntaxError

var 聲明的變量可以重復聲明,而且不會有任何警告或者提示,就這樣悄悄的覆蓋了一個值,隱患如變量提升一樣讓人擔憂。( ̄┰ ̄*)

而 let 聲明的變量如果進行重復聲明,則會直接拋出一個語法錯誤(是的,就是直接明確地告訴你:你犯了一個相當?shù)图壍恼Z法錯誤哦)

Const

無變量提升
有塊級作用域
禁止重復聲明

前 3 點跟 let 一個套路,就不多說了

禁止重復賦值

const DEV = true;
DEV = false; // => TypeError

基于靜態(tài)常量的定義我們可以很明顯知道,const 聲明的常量一經(jīng)聲明便不能再更改其值,無需多說。

必須附初始值

const DEV; // => SyntaxError

也是基于定義,const 聲明的常量既然一經(jīng)聲明便不能再更改其值,那聲明的時候沒有附初始值顯然是不合理的,一個沒有任何值的常量是沒有意義的,浪費內(nèi)存。

新增庫函數(shù)
  ES6 新增了許多(相當多)的庫函數(shù),這里只介紹一些比較常用的。

題外話:多了解一下內(nèi)建函數(shù)與方法有時候可以很方便高效地解決問題。有時候絞盡腦汁寫好的一個算法,沒準已經(jīng)有內(nèi)建函數(shù)實現(xiàn)了!而且內(nèi)建函數(shù)經(jīng)過四海八荒眾神的考驗,性能一定不錯,哈哈。

Number

Number.EPSILON
Number.isInteger(Infinity); // => false
Number.isNaN('NaN');        // => false

首先是 ? 這個常量屬性,表示小數(shù)的極小值,主要用來判斷浮點數(shù)計算是否精確,如果計算誤差小于該閾值,則可以認為計算結(jié)果是正確的。

然后是 isInteger() 這個方法用來判斷一個數(shù)是否為整數(shù),返回布爾值。

最后是 isNaN() 用來判斷入?yún)⑹欠駷?NaN。是的,我們再也不用通過 NaN 不等于 NaN 才能確定一個 NaN 就是 NaN 這種反人類的邏輯來判斷一個 NaN 值了!

if(NaN !== NaN) {
    console.log("Yes! This is actually the NaN!");
}```
  另外還有兩個小改動:兩個全局函數(shù) parseInt() 與 parseFloat() 被移植到 Number 中,入?yún)⒎磪⒈3植蛔儭_@樣所有數(shù)字處理相關(guān)的都在 Number 對象上嘞!規(guī)范多了。

String

'abcde'.includes('cd'); // => true
'abc'.repeat(3); // => 'abcabcabc'
'abc'.startsWith('a'); // => true
'abc'.endsWith('c'); // => true````

1、inclueds() 方法用來判斷一個字符串中是否存在指定字符串
2、repeat() 方法用來重復一個字符串生成一個新的字符串
3、startsWith() 方法用來判斷一個字符串是否以指定字符串開頭,可以傳入一個4、整數(shù)作為第二個參數(shù),用來設(shè)置查找的起點,默認為 0,即從字符串第一位開始查找
5、endsWith() 與 startsWith() 方法相反

Array

Array.from(document.querySelectorAll('*')); // => returns a real array.
[0, 0, 0].fill(7, 1); // => [0, 7, 7]
[1, 2, 3].findIndex(function(x) {
    return x === 2;
}); // => 1
['a', 'b', 'c'].entries(); // => Iterator [0: 'a'], [1: 'b'], [2: 'c']
['a', 'b', 'c'].keys();    // => Iterator 0, 1, 2
['a', 'b', 'c'].values();  // => Iterator 'a', 'b', 'c'
// Before
new Array();        // => []
new Array(4);       // => [,,,]
new Array(4, 5, 6); // => [4, 5, 6]
// After
Array.of();         // => []
Array.of(4);        // => [4]
Array.of(4, 5, 6);  // => [4, 5, 6]
  ````
       首先是 from() 方法,該方法可以將一個類數(shù)組對象轉(zhuǎn)換成一個真正的數(shù)組。還記得我們之前常寫的 Array.prototype.slice.call(arguments) 嗎?現(xiàn)在可以跟他說拜拜了~
  之后的 fill() 方法,用來填充一個數(shù)組,第一個參數(shù)為將要被填充到數(shù)組中的值,可選第二個參數(shù)為填充起始索引(默認為 0),可選第三參數(shù)為填充終止索引(默認填充到數(shù)組末端)。
      findIndex() 用來查找指定元素的索引值,入?yún)楹瘮?shù),函數(shù)形參跟 map() 方法一致,不多說。最終輸出符合該條件的元素的索引值。
        entries()、keys()、values() 三個方法各自返回對應(yīng)鍵值對、鍵、值的遍歷器,可供循環(huán)結(jié)構(gòu)使用。
  最后一個新增的 of() 方法主要是為了彌補 Array 當做構(gòu)造函數(shù)使用時產(chǎn)生的怪異結(jié)果。
```
Object

let target = {
    a: 1,
    b: 3
};
let source = {
    b: 2,
    c: 3
};

Object.assign(target, source); // => { a: 1, b: 2, c: 3}

assign() 方法用于合并兩個對象,不過需要注意的是這種合并是淺拷貝。可能看到這個方法我們還比較陌生,不過了解過 jQuery 源碼的應(yīng)該知道 $.extend() 這個方法,例如在下面這個粗糙的 $.ajax() 模型中的應(yīng)用:

$.ajax = function(opts) {
    var defaultOpts = {
        method: 'GET',
        async: true,
        //...
    };
    opts = $.extend(defaultOpts, opts);
}```
  從這我們可以看到 TC39 也是在慢慢吸收百家所長,努力讓 JavaScript 變得更好,更方便開發(fā)者的使用。

Object 新增的特性當然不止這一個 assign() 方法,一共增加了十多個新特性,特別是對屬性或方法名字面量定義的增強方面,很值得一看,感興趣的自行查找資料進行了解哈,印象會更深刻!
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容