ES6的一些常用特性


由於公司的前端業務全部基於ES6開發,於是給自己開個小灶補補ES6的一些常用特性。原來打算花兩天學習ES6的,結果花了3天才勉強過了一遍阮老師的ES6標准入門,下面羅列一些自己經常用到的ES6特性。

Default Parameters(默認參數)

還記得我們以前不得不通過下面方式來定義默認參數:

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

 

但在ES6,我們可以直接把默認值放在函數申明里:

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

 

Multi-line Strings (多行字符串)

ES6的多行字符串是一個非常實用的功能。在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';
var fourAgreements = 'You have the right to be you.n
    You can only be you when you do your best.';

然而在ES6中,僅僅用反引號就可以解決了:

var 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
    Had worn them really about the same,`;
var fourAgreements = `You have the right to be you.
    You can only be you when you do your best.`;

Template Literals(模板對象)

在其它語言中,使用模板和插入值是在字符串里面輸出變量的一種方式。因此,在ES5,我們可以這樣組合一個字符串:

var name = 'Your name is ' + first + ' ' + last + '.';
var url = 'http://localhost:3000/api/messages/' + id;

幸運的是,在ES6中,我們可以使用新的語法$ {NAME},並把它放在反引號里

var name = `Your name is ${first} ${last}. `;
var url = `http://localhost:3000/api/messages/${id}`;

塊級作用域

ES6提出了兩個新的聲明變量的命令:letconst。其中,let完全可以取代var,因為兩者語義相同,而且let沒有副作用。

(1).使用let 取代 var

1.for循環的計數器,就很合適使用let命令。

/*  let */
for (let i = 0; i < 10; i++) {}
console.log(i);   //ReferenceError: i is not defined

/* var */
for (var i = 0; i < 10; i++) {}
console.log(i);   // 10

2.var命令存在變量提升效用,let命令沒有這個問題。

/* let */
if(1) {
  console.log(x); // ReferenceError
  let x = 'hello';
}

/* var */
if(1) {
  console.log(x); // hello
  var x = 'hello';
}

//使用var,有輸出,這違反了變量先聲明后使用的原則。所以,建議不再使用var命令,而是使用let命令取代。

(2)全局常量和線程安全

letconst之間,建議優先使用const,尤其是在全局環境,不應該設置變量,只應設置常量。

const優於let有幾個原因。一個是const可以提醒閱讀程序的人,這個變量不應該改變;另一個是const比較符合函數式編程思想,運算不改變值,只是新建值,而且這樣也有利於將來的分布式運算;最后一個原因是 JavaScript 編譯器會對const進行優化,所以多使用const,有利於提供程序的運行效率,也就是說letconst的本質區別,其實是編譯器內部的處理不同。

// bad
var a = 1, b = 2, c = 3;

// good
const a = 1;
const b = 2;
const c = 3;

// best
const [a, b, c] = [1, 2, 3];

解構賦值

1.使用數組成員對變量賦值時,優先使用解構賦值。

const arr = [1, 2, 3, 4];

// bad
const first = arr[0];
const second = arr[1];

// good
const [first, second] = arr;

2.函數的參數如果是對象的成員,優先使用解構賦值。

// bad
function getFullName(user) {
  const firstName = user.firstName;
  const lastName = user.lastName;
}

// good
function getFullName(obj) {
  const { firstName, lastName } = obj;
}

// best
function getFullName({ firstName, lastName }) {
}

3.如果函數返回多個值,優先使用對象的解構賦值,而不是數組的解構賦值。(因為數組的元素是按次序排列的,變量的取值由它的位置決定;而對象的屬性沒有次序,變量必須與屬性同名,才能取到正確的值。)

// bad
function processInput(input) {
  return [left, right, top, bottom];
}

// good
function processInput(input) {
  return { left, right, top, bottom };
}

const { left, right } = processInput(input);

數組

1.使用擴展運算符(...)拷貝數組。

// bad
const len = items.length;
const itemsCopy = [];
let i;

for (i = 0; i < len; i++) {
  itemsCopy[i] = items[i];
}

// good
const itemsCopy = [...items];

2.使用Array.from方法,將類似數組的對象轉為數組。(包括ES6新增的數據結構Set和Map)

const foo = document.querySelectorAll('.foo');
const nodes = Array.from(foo);

函數

簡單的、單行的、不會復用的函數,建議采用箭頭函數。如果函數體較為復雜,行數較多,還是應該采用傳統的函數寫法。

1.立即執行函數可以寫成箭頭函數的形式。

(() => {
  console.log('Welcome to the Internet.');
})();

2.那些需要使用函數表達式的場合,盡量用箭頭函數代替。因為這樣更簡潔,而且綁定了this。

// bad
[1, 2, 3].map(function (x) {
  return x * x;
});

// good
[1, 2, 3].map((x) => {
  return x * x;
});

// best
[1, 2, 3].map(x => x * x);

3.箭頭函數取代Function.prototype.bind,不應再用self/_this/that綁定 this。

// bad
const self = this;
const boundMethod = function(...params) {
  return method.apply(self, params);
}

// acceptable
const boundMethod = method.bind(this);

// best
const boundMethod = (...params) => method.apply(this, params);

4.不要在函數體內使用arguments變量,使用rest運算符(...)代替。因為rest運算符顯式表明你想要獲取參數,而且arguments是一個類似數組的對象,而rest運算符可以提供一個真正的數組。

// bad
function concatenateAll() {
  const args = Array.prototype.slice.call(arguments);
  return args.join('');
}

// good
function concatenateAll(...args) {
  return args.join('');
}

Map結構

注意區分Object和Map,只有模擬現實世界的實體對象時,才使用Object。如果只是需要key: value的數據結構,使用Map結構。因為Map有內建的遍歷機制。

let map = new Map(arr);

for (let key of map.keys()) {
  console.log(key);
}

for (let value of map.values()) {
  console.log(value);
}

for (let item of map.entries()) {
  console.log(item[0], item[1]);
}

Class

用Class,取代需要prototype的操作。因為Class的寫法更簡潔,更易於理解。

// bad
function Queue(contents = []) {
  this._queue = [...contents];
}
Queue.prototype.pop = function() {
  const value = this._queue[0];
  this._queue.splice(0, 1);
  return value;
}

// good
class Queue {
  constructor(contents = []) {
    this._queue = [...contents];
  }
  pop() {
    const value = this._queue[0];
    this._queue.splice(0, 1);
    return value;
  }
}

使用extends實現繼承,因為這比ES5的通過修改原型鏈實現繼承,要清晰和方便很多。

// bad
const inherits = require('inherits');
function PeekableQueue(contents) {
  Queue.apply(this, contents);
}
inherits(PeekableQueue, Queue);
PeekableQueue.prototype.peek = function() {
  return this._queue[0];
}

// good
class PeekableQueue extends Queue {
  peek() {
    return this._queue[0];
  }
}

再來看一個react中的常見例子:

class ReactCounter extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }
}

可以看到里面有一個constructor方法,這就是構造方法;而super關鍵字,它在這里表示父類的構造函數,用來新建父類的this對象。

這里做點補充:ES5的繼承,實質是先創造子類的實例對象this,然后再將父類的方法添加到this上面(Parent.apply(this))。ES6的繼承機制完全不同,實質是先創造父類的實例對象this(所以必須先調用super方法),然后再用子類的構造函數修改this

模塊

1.使用import取代require

// bad
const moduleA = require('moduleA');
const func1 = moduleA.func1;
const func2 = moduleA.func2;

// good
import { func1, func2 } from 'moduleA';

2.使用export取代module.exports

// commonJS的寫法
var React = require('react');

var Breadcrumbs = React.createClass({
  render() {
    return <nav />;
  }
});

module.exports = Breadcrumbs;

// ES6的寫法
import React from 'react';

class Breadcrumbs extends Component {
  render() {
    return <nav />;
  }
}  //這里不要加逗號

export default Breadcrumbs

其它

ES6里面還要很多比較重要的概念,特別是Generator函數,Promise對象等,個人認為在node開發使用它們是非常友好的。日后若水平提高了再來敘談。 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM