ES6語言特性的總結(1)

雖然在編寫項目的過程當中,也會用到ES6的語法以及新特性。但感受學習的不是特別系統,索性這兩天從新刷了一下Understanding The ES6,也對ES6有了更深的理解。這裏,針對感受應用比較多,知識點比較重要的部分作了一下總結。內容有點多,所以預計將分爲三個部分。javascript

塊級綁定-做用域

在ES5中,有一個知識難點,就是變量提高和做用域。而這一部分之因此讓人困擾,則是由於JS中變量的聲明方式會影響變量實際的建立位置。前端

有一條規則是:使用var關鍵字聲明的變量,不管其實際聲明位置在何處,都會被聲明與函數的頂部,這就是變量提高(hosting)。java

ES6中爲了讓變量的生命週期更加可控,引入了塊級聲明。即,讓所聲明的變量在指定塊的做用域外沒法被訪問。ES6主要引入了兩個新的關鍵字,letconstnode

let

letvar相似,不一樣是的,let聲明的變量不會存在變量提高的狀況。所以,下面這個代碼中:git

{
  let a = 1;
}

console.log(a);複製代碼

是沒法訪問到a變量的。es6

另外一個限制的地方是,禁止重複聲明相同的變量。github

var a = 1;
let a = 2;複製代碼

上面的代碼也會報錯。數組

const

這個關鍵字也是限制了變量提高以及重複聲明,並且變量值是不可更改的。瀏覽器

const a = 1;
a = 2//報錯複製代碼

可是,若是綁定的是對象,能夠更改對象屬性值。微信

const person = { 'name': 'xiaoming', 'age': 12};
person.name = 'zhangsan';
console.log(person.name); //zhangsan複製代碼

暫時性死區

利用letconst聲明的變量,代碼在訪問到聲明處前都是禁止訪問的。

let a = 2;
a = b; // b is not defined
let b = 3;複製代碼

循環中的let和const聲明

請看下面這段代碼:

var array = [];

for(var i = 0 ; i < 10; i++) {
    array.push(function() {
      console.log(i);
    });
}

array.forEach(function(func) { func(); }); //會輸出10次10複製代碼

使用var聲明的變量,會在每次循環中被共享了。所以,在循環內部建立的函數都用於同一個變量的引用。一般解決這種方式,在ES5中會採用閉包的方式。而ES6中,可使用let關鍵字

var array = [];

for(let i = 0 ; i < 10; i++) {
    array.push(function() {
      console.log(i);
    });
}

array.forEach(function(func) { func(); }); //會依次輸出0...9複製代碼

這是由於let關鍵字在每次循環中,都會建立一個新的i變量,而循環內部的函數獲取的i變量其實都是副本。

const關鍵字不能夠用在傳統的for循環中,可是能夠用在for...offor … in語法中。使用效果和let同樣。

函數

ES6中對函數的功能作了新的擴展,使之使用起來更方便。

箭頭函數

自從有了箭頭函數,在遇到回調函數寫法的時候,就特別方便。固然它的功能確定不止於此。箭頭函數的語法像這樣:

(變量名,[其餘變量名]) => { //函數體} 
//有如下幾種變形
(value1, value2) => {return value1 + value2;} 
(value1, value2) => value1 + value2; //函數體只有一條return語句的時候,能夠省略return關鍵字和{}
value => value1 + 1; //單參數函數時候,能夠省略括號複製代碼

是傳統函數寫法的一種便捷寫法,同時,有如下幾個特色:

  1. 不容許重複的具名參數
  2. 沒有arguments對象
  3. 不能更改this,在整個函數聲明週期內其值會保持不變,所以,在遇到this問題時,不用再像ES5以前的時期使用相似var self =thisbind(this)之類的方法了。
  4. 不能被new調用
  5. 沒有this、super、arguments、也沒有new.target綁定

默認參數和不具名參數

先看下面這個例子,同時使用了默認參數和不具名參數(也叫作剩餘參數):

//num1若是不傳值或者爲undefined的話爲0, num2是一個數組表明後續傳進來的參數集合
function add(num1 = 0, ...num2) {
     num2.forEach(i => num1 = num1 + i);
     return num1;
}

console.log(add(undefined,2)); //2

console.log(add(undefined,2,3)); //5

console.log(add(1,2,3)); //6複製代碼

採用了默認參數值時,仍然可使用arguments對象來反應真實函數的調用狀態, 而arguments對象也能夠和不具名參數進行協同工做。

function add(num1 = 1, num2 = 1) {
    console.log(arguments);
}

add(1); //[1]
add(2, 3); //[2,3]
add(); //[]
add(2,3,4,5,6); //[2,3,4,5,6]複製代碼

同時,函數的默認值甚至能夠利用函數來動態生成,而非寫死的,如:

function getNum() {
  return parseInt(Math.random() * 10);
}

function add(num1 = getNum(), num2 = 1) {
  console.log(num1 + num2);
}

//每次調用的結果是隨機的,如下爲某一次調用的結果
add(); // 8
add(); // 4複製代碼

須要注意的是,函數的不具名參數是不可以在對象的setter上使用的,這是由於setter只接受單一值做爲它的參數。

擴展運算符

這三個點運算符用在函數聲明的時候,就是不具名參數,可是它同時也能用在解構對象上,所以,在函數調用過程當中,可使用該運算符,進行多個參數傳遞。如

var randomArray = [2,3,1231,455,231,23,553];
console.log(Math.max(...randomArray)); //1231複製代碼

new.target

這是ES6函數對象的元屬性,能夠經過檢查new.target對象是否被定義,能夠判斷函數是否經過new進行調用。

function Cat() {
  if(new.target === undefined) {
    console.log('this is not called by NEW keyword');
  }else {
    console.log('this is called by NEW keyword');
  }
}

new Cat(); //this is called by NEW keyword
Cat.call(this); //this is not called by NEW keyword複製代碼

原理方面,其實就是當函數的構造器(constructor)方法被調用時,new.target 會被填入 new 運算符的做用目標,該目標一般是新建立的對象實例的構造器,而且會成爲函數體內部的 this 值。而若call方法被執行的時候, new.target 的值則會是undefined

解構

解構的意思是將數據結構分解爲更小的部分,而ES6中引入瞭解構的方式目的就是可以更好地提取數據。

##對象解構
直接上例子:

let { type, name } = node //普通解構
let { type, name, value = true } = node; //默認值解構
let { type: localType, name: localName } = node; //賦值給不一樣的本地對象
let { loc: { start: localStart }} = node; //嵌套的解構方式,等同於localStart = node.loc.start複製代碼

以上須要注意的是,當解構賦值表達式的右側( = 後面的表達式)的計算結果爲 null 或 undefined 時,會拋出錯誤。

##數組解構

數組解構時,解構做用在數組內部的位置上,而不是做用在對象的具名屬性上。

let [ , , thirdColor ] = colors;

let [ firstColor, secondColor = "green" ] = colors; //默認值

let [ firstColor, [ secondColor ] ] = colors; //嵌套解構

let [ firstColor, ...restColors ] = colors; //剩餘項

[a, b] = [b, a]; //數組解構賦值有一個很是獨特的用例,能輕易地互換兩個變量的值複製代碼

參數解構

function doSomething(value1, value2, {value3, value4, value5}) {

}複製代碼

須要注意的是默認狀況下調用函數時未給參數解構傳值會拋出錯誤。但若你要求它是可選的,能夠給解構的參數提供默認值來處理這種行爲。

function dosomething(value1, value2, {value3, value4, value5} = {}) {
  //dosomething
}複製代碼

擴展的對象功能

在ES6中也對對象的使用方式作了進一步的擴展,使其不管是在代碼編寫形式層面仍是底層操做對象的層面都有了更多的特性。

對象類別

在ES6規範中,定義了對象的每種類別:

1.普通對象:擁有JS對象全部默認的內部行爲

2.奇異對象:有別於默認的內部行爲的對象

3.標準對象:是在ES6中被定義的對象,能夠是普通對象也能夠是奇異對象。

4.內置對象:在腳本開始運行時由JS運行環境(瀏覽器或Node)提供的對象。全部標準對象都是內置對象。

屬性初始化器

當對象的一個屬性名稱與本地變量名相同的時候,能夠省略冒號和值,如:

function createPerson(name, age) {
  return {
    name,
    age
  }
}
//等同於
function createPerson(name, age) {
    return {
      name: name,
      age: age
    }
}複製代碼

方法簡寫

方法簡寫以下:

var person = {
  name: 'nihao',
  getName() {
    return this.name;
  }
}

//等同與
var person = {
  name: 'nihao',
  getName: function() {
    return this.name;
  }
}複製代碼

須要注意的是,使用方法簡寫,在方法內部可使用super方法,而傳統的寫法是沒法使用的。

計算性屬性名

屬性名可使用拼接的寫法,如:

var name = 'name';

var person = {
  ['first' + name]: 'scq',
  ['last' + name]: '000',
  getName() {
    return this.firstname + this.lastname;
  }
}複製代碼

對於某些須要動態生成屬性名的場合,寫法更加方便。

Object.is方法

爲了不在對象比較過程當中的強制對象轉換。一般該方法的運行結果和===同樣,可是+0-0,NaNNaN不相同。

Object.assign(source, target) 方法

該方法接受一個接收者,以及任意數量的供應者,並會返回接收者。我一般在使用的時候,用來作繼承或者說深度拷貝??。

const person = {
      name: 'scq000',
      age: 23,
      addressInfo: {
        city: 'zs',
        address: 'some address'
      }
    }
    const person2 = Object.assign({}, person);複製代碼

Object.assign() 方法接受任意數量的供應者,而接收者會按照供應者在參數中的順序來依次接收它們的屬性。這意味着在接收者中,第二個供應者的屬性可能會覆蓋第一個供應者的。

關於重複的對象字面量屬性

ES6 移除了重複屬性的檢查,嚴格模式與非嚴格模式都再也不檢查重複的屬性。當存在重複屬性時,排在後面的屬性的值會成爲該屬性的實際值。

自有屬性的枚舉順序

1.全部的數字類型鍵,按升序排列。

2.全部的字符串類型鍵,按被添加到對象的順序排列。

3.全部的符號類型鍵,也按添加順序排列。

修改對象的原型

對象原型的實際值被存儲在一個內部屬性[[Prototype]] 上, Object.getPrototypeOf() 方法會返回此屬性存儲的值,而 Object.setPrototypeOf() 方法則可以修改該值。ES6 經過添加 Object.setPrototypeOf()方法而改變了這種假定,此方法容許你修改任意指定對象的原型。它接受兩個參數:須要被修改原型的對象,以及將會成爲前者原型的對象。
由於這個特性的添加,可使用 super 進行簡單的原型訪問。super 是指向當前對象的原型的一個指針,實際上就是 Object.getPrototypeOf(this) 的值。這個功能在使用ES6類的繼承的時候,提供了更好的訪問父類的方式。

class Animal {
  constructor(name, size) {
    this.name = name;
    this.size = size;
  }
}

class Cat extends Animal {
  constructor(size) {
    super('cat', size);
  }
}複製代碼

系列二請點這裏


本文對你有幫助?歡迎掃碼加入前端學習小組微信羣:

相關文章
相關標籤/搜索