你需要了解的 ES6 語法

 

ES6 是下一代 JavaScript 語法標準,比起 ES5 有很大的變化。標準委員會每年發佈一次當年度的新標準,目前最新的標準是《ES2018 標準》,因此 ES6 是一個動態的標準,每年都會發生一些變化。

React 大量使用 ES6 語法,本文介紹其中一些最重要的語法點。完整的 ES6 介紹請參考 http://es6.ruanyifeng.com/

let 和 const

letconst命令用於聲明變量。

let聲明的變量是可變的,const聲明的變量是不可變的。

let foo = 1;
foo = 2;

const bar = 1;
bar = 2; // 報錯

上面代碼中,let聲明的變量foo是可以重新賦值,但是如果對bar聲明的變量重新賦值,就會報錯。

注意,如果const聲明的變量指向一個對象,那麼該對象的屬性是可變的。

const foo = {
  bar: 1
};

foo.bar = 2;

上面代碼中,變量foo本身是不可變的,即foo不能指向另一個對象。但是,對象內部的屬性是可變的,這是因爲這時foo保存的是一個指針,這個指針本身不可變,但它指向的對象本身是可變的。

解構賦值

ES6 允許按照一定模式,從數組和對象中提取值,對變量進行賦值,這被稱爲解構(Destructuring)。

let [a, b, c] = [1, 2, 3];

上面代碼表示,可以從數組中提取值,按照對應位置,對變量賦值。

解構賦值不僅可以用於數組,還可以用於對象。

let { foo, bar } = { foo: "aaa", bar: "bbb" };
foo // "aaa"
bar // "bbb"

解構賦值時,還可以設置默認值。

let [x, y = 'b'] = ['a']; // x='a', y='b'

上面代碼中,變量y解構賦值時沒有取到值,所以默認值就生效了。

對象的簡潔表示法

ES6 允許直接寫入變量和函數,作爲對象的屬性和方法。這樣的書寫更加簡潔。

const foo = 'bar';
const baz = { foo };
baz // {foo: "bar"}

除了屬性簡寫,方法也可以簡寫。

const o = {
  method() {
    return "Hello!";
  }
};

// 等同於

const o = {
  method: function() {
    return "Hello!";
  }
};

箭頭函數

ES6 允許使用“箭頭”(=>)定義函數。

var f = v => v;

// 等同於
var f = function (v) {
  return v;
};

如果箭頭函數不需要參數或需要多個參數,就使用一個圓括號代表參數部分。

var f = () => 5;
// 等同於
var f = function () { return 5 };

var sum = (num1, num2) => num1 + num2;
// 等同於
var sum = function(num1, num2) {
  return num1 + num2;
};

如果箭頭函數的代碼塊部分多於一條語句,就要使用大括號將它們括起來,並且使用return語句返回。

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

rest 參數

ES6 引入 rest 參數(形式爲...變量名),用於獲取函數的多餘參數,這樣就不需要使用arguments對象了。rest 參數搭配的變量是一個數組,該變量將多餘的參數放入數組中。

function add(...values) {
  let sum = 0;

  for (var val of values) {
    sum += val;
  }

  return sum;
}

add(2, 5, 3) // 10

上面代碼的add函數是一個求和函數,利用 rest 參數,可以向該函數傳入任意數目的參數。

擴展運算符

擴展運算符(spread)是三個點(...)。它好比 rest 參數的逆運算,將一個數組轉爲用逗號分隔的參數序列。

console.log(...[1, 2, 3])
// 1 2 3

console.log(1, ...[2, 3, 4], 5)
// 1 2 3 4 5

[...document.querySelectorAll('div')]
// [<div>, <div>, <div>]

對象也可以使用擴展運算符。

let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
x // 1
y // 2
z // { a: 3, b: 4 }

class

ES6 允許新建“類”(class)。

class SkinnedMesh extends THREE.Mesh {
  constructor(geometry, materials) {
    super(geometry, materials);

    this.idMatrix = SkinnedMesh.defaultMatrix();
    this.bones = [];
    this.boneMatrices = [];
    //...
  }
  update(camera) {
    //...
    super.update();
  }
  get boneCount() {
    return this.bones.length;
  }
  set matrixType(matrixType) {
    this.idMatrix = SkinnedMesh[matrixType]();
  }
  static defaultMatrix() {
    return new THREE.Matrix4();
  }
}

上面是一個類的定義。

  • constructor():構造函數,新建實例的時候,自動調用這個方法。
  • extends:第一行的extends關鍵字表示繼承某個父類。
  • super:子類方法裏面的super指代父類。
  • get():get是取值器,讀取該方法定義的屬性時,會自動執行指定的代碼。
  • set():set是賦值器,賦值該方法定義的屬性時,會自動執行指定的代碼。
  • static:方法前面加上static關鍵字,表示該方法是靜態方法,定義在類上面,而不是定義在實例對象上面,以上面爲例,就是SkinnedMesh.defaultMatrix()這樣調用。

定義了類以後,就可以新建實例了。

const instance = new SkinnedMesh();

Promise 對象

Promise 是 ES6 引入的封裝異步操作的統一接口。它返回一個對象,包含了異步操作的信息。

Promise 本身是一個構造函數,提供了resolvereject兩個方法。一旦異步操作成功結束,就調用resolve方法,將 Promise 實例對象的狀態改爲resolved,一旦異步操作失敗,就調用reject方法,將 Promise 實例的狀態改成rejected

function timeout(duration = 0) {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, duration);
  })
}

上面代碼中,timeout函數返回一個 Promise 實例,在指定時間以後,將狀態改爲resolved

var p = timeout(1000).then(() => {
  return timeout(2000);
}).then(() => {
  throw new Error("hmm");
}).catch(err => {
  return Promise.all([timeout(100), timeout(200)]);
})

一旦 Promise 實例的狀態改變以後,就可以使用then()方法指定下面將要執行的函數,catch()方法用來處理rejected狀態的情況。

module

ES6 意義最重大的語法變化,就是引入了模塊(module)。

一個模塊內部,使用export命令輸出對外的接口。

// lib/math.js
export function sum(x, y) {
  return x + y;
}
export var pi = 3.141593;

上面的模塊輸出了sumpi兩個接口。

import命令用於引入該模塊。

// app.js
import * as math from "lib/math";
alert("2π = " + math.sum(math.pi, math.pi));

上面代碼中,*表示引入所有接口,也可以只引入指定的接口。

// otherApp.js
import {sum, pi} from "lib/math";
alert("2π = " + sum(pi, pi));

轉: https://www.yuque.com/ant-design/course/byllph

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章