ES6特性

前言

ES全稱ECMAScript,ECMAScript是ECMA制定的標準化腳本語言。目前JavaScript使用的ECMAScript版本爲ECMAScript-262。程序員

ECMAScript 標準創建在一些原有的技術上,最爲著名的是 JavaScript (網景) 和 JScript (微軟)。它最初由網景的 Brendan Eich 發明,第一次出現是在網景的 Navigator 2.0 瀏覽器上。Netscape 2.0 以及微軟 Internet Explorer 3.0 後序的全部瀏覽器上都有它的身影。編程

ECMAScript版本 發佈時間 新增特性
ECMAScript 2009(ES5) 2009年11月 擴展了Object、Array、Function的功能等
ECMAScript 2015(ES6) 2015年6月 類,模塊化,箭頭函數,函數參數默認值等
ECMAScript 2016(ES7) 2016年3月 includes,指數操做符
ECMAScript 2017(ES8) 2017年6月 sync/await,Object.values(),Object.entries(),String padding等

ES6 特性

下面會介紹幾個比較經常使用的新特性:數組

  • 變量let和const
  • 箭頭函數
  • 解構賦值
  • 模板字符串
  • 默認參數
  • 對象屬性簡寫
  • Promise
  • 類Class
  • 模塊Module

一、變量let、const和var

let

  1. let爲JavaScript新增了塊級做用,let聲明的變量只在其所在代碼塊有效;
  2. 不存在變量提高,必須先定義後使用promise

    console.log(foo);//ReferenceError
    let foo = 3;
  3. 暫時性死區 只要塊級做用域內存在let命令,他聲明的變量就是綁定在這個區域,再也不受外部影響;ES6 明確規定,若是區塊中存在let和const命令,這個區塊對這些命令聲明的變量,從一開始就造成了封閉做用域。凡是在聲明以前就使用這些變量,就會報錯。瀏覽器

    if (true) {
      // TDZ開始
      tmp = 'abc'; // ReferenceError
      console.log(tmp); // ReferenceError
    
      let tmp; // TDZ結束
      console.log(tmp); // undefined
    
      tmp = 123;
      console.log(tmp); // 123
    }
  4. 不容許重複聲明

const

  1. const用來聲明常量,一旦聲明,其值就不能改變;
  2. const一旦聲明常量就必須當即賦值。只聲明不賦值就會報錯
  3. 和let命令相同:只能在所聲明的塊級做用域內有效
  4. const命令聲明的常量也不能提高,一樣存在暫時性死區,只能在聲明後使用
  5. onst也不能重複聲明常量
  6. const命令只是保證變量指向的地址不變,並不保證改地址的數據不變異步

    const foo = {};
    foo.prop = 123;
    
    foo.prop;//123

二、箭頭函數

ES6容許使用箭頭(=>)定義函數。 ide

=>不僅是關鍵字function的簡寫,它還帶來了其它好處。箭頭函數與包圍它的代碼共享同一個this,能幫你很好的解決this的指向問題。有經驗的JavaScript開發者都熟悉諸如var self = this;或var that = this這種引用外圍this的模式。但藉助=>,就不須要這種模式了。模塊化

若是箭頭函數不須要參數或者須要多個參數,就是用圓括號表明參數部分。異步編程

let sum = (num1,num2) => {
    return num1+num2
}

箭頭函數的特色:函數

  1. 函數體內的this對象就是定義時所在的對象,而不是他使用時所在的對象
  2. 不能夠當作構造函數,也就是說不可使用new命令,不然會拋出一個錯誤
  3. 不可使用arguments對象,該對象在函數體內不存在,若是要使用能夠用rest參數代替
  4. 不可使用yield命令,所以箭頭函數不能用做Generator函數
//箭頭函數中this指向固定
function foo() {
  setTimeout(() => {
    console.log('id:', this.id);
  }, 100);
}

var id = 21;

foo.call({ id: 42 });
// id: 42

三、解構賦值

ES6容許按照必定的模式,從數組和對象中提取值,對變量進行賦值,這被稱爲 解構

變量解構

  1. 數組解構

    let [x,y,z] = new Set(["a","b","c"]);
    x //a
    
    let [foo = true] = [];
    foo //true
    
    let [x,y='b'] = [a];
    let [x,y='b'] = [a,undefined];
    //以上兩種輸出都是 
    x //a
    y //b
  2. 對象解構

    對象的解構與數組的解構有一個重要的不一樣;數組的元素是按次序排列的,變量的取之由他的位置決定;而對象的屬性是沒有次序的,變量必須與屬性同名,才能取到正確的值

    let {bar,foo} = {foo:"aaa",bar:"bbb"};
    bar // bbb
    foo //aaa
    let {baz,foo} = {foo:"aaa",bar:"bbb"};
    baz //undefined
    
    若是變量名與屬性名不一致
    let {first:f, last:l} = {first:"hello", last:"bye"};
    first //undefined
    f //hello
    last //undefined
    l //bye

    也就是說對象解構賦值的內部機制,是先找到同名屬性,而後在賦值給對應的變量,真正被賦值的是後者,而不是前者

函數解構

參數默認值能夠與解構賦值的默認值結合使用

function foo(x,y=5){
    console.log(x,y);
}
foo({});//undefined,5
foo(1);//1,5
foo(1,2)//1,2

四、模板字符串

模版字符串是加強版的字符串,用反引號(`)標識;他能夠看成普通字符串使用,也能夠用來定義多行字符串,或者在字符串中嵌入變量

let name="Tom",time="today";
`hello ${name},how arw your ${time}`

大括號裏面能夠聽任意的JavaScript表達式,能夠進行運算,以及引用對象屬性。

let x = 1;
let y = 2;
`${x}+${y}=${x+y}`//1+2=3

let obj = {x:1,y:3};
`${obj.x+obj.y}`
// 4

模版字符串中還能調用函數

function fn(){
    return "hehe";
}
`test ${fn()}`
// test hehe

多行字符串

//ES5中
var roadPoem = 'Then took the other, as just as fair,nt'
    + 'And having perhaps the better claimnt'
    + 'Because it was grassy and wanted wear,nt'
    + 'Though as for that the passing therent'
    + 'Had worn them really about the same,nt';


//ES6
let roadPoem = `Then took the other, as just as fair,
    And having perhaps the better claim
    Because it was grassy and wanted wear,
    Though as for that the passing there

五、默認參數

咱們之前不得不經過下面方式來定義默認參數

var link = function (height, color, url) {
    var height = height || 50;
    var color = color || 'red';
    var url = url || 'http://azat.co';
    ...
}

一切工做都是正常的,直到參數值是0後,就有問題了,由於在JavaScript中,0表示false,它是默認被hard-coded的值,而不能變成參數自己的值。固然,若是你非要用0做爲值,咱們能夠忽略這一缺陷而且使用邏輯OR就好了!但在ES6,咱們能夠直接把默認值放在函數申明裏:

let link = function(height = 50, color = 'red', url = 'http://azat.co') {
    ...
}

六、對象屬性簡寫

ES5中對象必須包含屬性和值

const name='Ming',age='18',city='Shanghai';
const student = {
    name:name,
    age:age,
    city:city
};
console.log(student);//{name: "Ming", age: "18", city: "Shanghai"}

使用ES6的話就會變得很是簡潔

const name='Ming',age='18',city='Shanghai';
const student = {
    name,
    age,
    city
};
console.log(student);//{name: "Ming", age: "18", city: "Shanghai"}

七、Promise

Promise 是異步編程的一種解決方案,比傳統的解決方案——回調函數和事件——更合理和更強大。它由社區最先提出和實現,ES6 將其寫進了語言標準,統一了用法,原生提供了Promise對象。

下面是一個簡單的用setTimeout()實現的異步延遲加載函數:

setTimeout(function(){
  console.log('Test!');
}, 1000);

在ES6中,咱們能夠用promise重寫:

let wait1000 =  new Promise((resolve, reject)=> {
  setTimeout(resolve, 1000);
}).then(()=> {
  console.log('Yay!');
});
const promise = new Promise((resolve, reject)=> {
  // ... some code
  if (/* 異步操做成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});

Promise構造函數接受一個函數做爲參數,該函數的兩個參數分別是resolve和reject。它們是兩個函數,由 JavaScript 引擎提供,不用本身部署。

resolve函數的做用是,將Promise對象的狀態從「未完成」變爲「成功」(即從 pending 變爲 resolved),在異步操做成功時調用,並將異步操做的結果,做爲參數傳遞出去;reject函數的做用是,將Promise對象的狀態從「未完成」變爲「失敗」(即從 pending 變爲 rejected),在異步操做失敗時調用,並將異步操做報出的錯誤,做爲參數傳遞出去。

Promise實例生成之後,能夠用then方法分別指定resolved狀態和rejected狀態的回調函數。

promise.then((value)=> {
  // success
}, (error)=> {
  // failure
});

then方法能夠接受兩個回調函數做爲參數。第一個回調函數是Promise對象的狀態變爲resolved時調用,第二個回調函數是Promise對象的狀態變爲rejected時調用。其中,第二個函數是可選的,不必定要提供。這兩個函數都接受Promise對象傳出的值做爲參數。

八、類Class

JavaScript 語言中,生成實例對象的傳統方法是經過構造函數。下面是一個例子。

function Point(x, y) {
  this.x = x;
  this.y = y;
}

Point.prototype.toString = function () {
  return '(' + this.x + ', ' + this.y + ')';
};

var p = new Point(1, 2);

上面這種寫法跟傳統的面嚮對象語言(好比 C++ 和 Java)差別很大,很容易讓新學習這門語言的程序員感到困惑。

ES6 提供了更接近傳統語言的寫法,引入了 Class(類)這個概念,做爲對象的模板。經過class關鍵字,能夠定義類。

基本上,ES6 的class能夠看做只是一個語法糖,它的絕大部分功能,ES5 均可以作到,新的class寫法只是讓對象原型的寫法更加清晰、更像面向對象編程的語法而已。上面的代碼用 ES6 的class改寫,就是下面這樣。

class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  toString() {
    return '(' + this.x + ', ' + this.y + ')';
  }
}

上面代碼定義了一個「類」,能夠看到裏面有一個constructor方法,這就是構造方法,而this關鍵字則表明實例對象。也就是說,ES5 的構造函數Point,對應 ES6 的Point類的構造方法。

Point類除了構造方法,還定義了一個toString方法。注意,定義「類」的方法的時候,前面不須要加上function這個關鍵字,直接把函數定義放進去了就能夠了。另外,方法之間不須要逗號分隔,加了會報錯。

九、Modules模塊

衆所周知,在ES6之前JavaScript並不支持本地的模塊。人們想出了AMD,RequireJS,CommonJS以及其它解決方法。如今ES6中能夠用模塊import 和export 操做了。
在ES5中,你能夠在 <script>中直接寫能夠運行的代碼(簡稱IIFE),或者一些庫像AMD。然而在ES6中,你能夠用export導入你的類。下面舉個例子,在ES5中,module.js有port變量和getAccounts 方法:

module.exports = {
  port: 3000,
  getAccounts: function() {
    ...
  }
}

在ES5中,main.js須要依賴require('module') 導入module.js:

var service = require('module.js');
console.log(service.port); // 3000

但在ES6中,咱們將用export 和 import。例如,這是咱們用ES6 寫的module.js文件庫:

export var port = 3000;
export function getAccounts(url) {
  ...
}

若是用ES6來導入到文件main.js中,咱們需用import 語法,例如:

import {port, getAccounts} from 'module';
console.log(port); // 3000

或者咱們能夠在main.js中把整個模塊導入, 並命名爲 service:

import * as service from 'module';
console.log(service.port); // 3000
相關文章
相關標籤/搜索