ES6標(biāo)準(zhǔn)匯總

本文轉(zhuǎn)載自我的個人博客

ES6新標(biāo)準(zhǔn)的知識點(diǎn)零散,經(jīng)常是看一遍就忘了,所以特別開了這一貼,作為一個ES6知識的匯總貼。主要講ES6的新命令的具體用法,以及與之前用法的區(qū)別。知識點(diǎn)不會講得很深,很多只是蜻蜓點(diǎn)水的講一下,適合當(dāng)作ES6的入門貼來看。本帖長期更新,實(shí)用向。

let 命令

ES6 新增了一個 let命令用來聲明變量。同樣是聲明變量,let與之前的var主要有以下幾點(diǎn)區(qū)別:

  1. let 聲明的變量不允許重復(fù)聲明:
  var a = 1;
  var a = 2;
  console.log(a); //輸出 2

  let b = 1;
  let b = 2;     //報(bào)錯
  console.log(b) ;

在一個大型項(xiàng)目中或者多人協(xié)助項(xiàng)目中,我們往往因?yàn)椴恢滥切┳兞恳呀?jīng)被聲明過了而重復(fù)聲明變量,導(dǎo)致之前變量的值被覆蓋。由于程序不會報(bào)錯,debug是很困難的,而現(xiàn)在的let命令很好的解決了這個問題。

  1. let 聲明的變量存在塊級作用域:
  function f1() {
    let n = 5;
    if (true) {
      let n = 10;
      console.log(n); //輸出 10
    }
    console.log(n); // 輸出 5
  }

上面的兩個代碼塊中擁有各自的變量n,不會相互影響。

再給一個例子:

  ///////// 使用 var /////////
  var printNumTwo;
  for (var i = 0; i < 3; i++) {
    if(i === 2){
      printNumTwo = function() {
        return i;
      };
    }
  }
  console.log(printNumTwo());
  // returns 3
  
  ///////// 使用 let /////////
  'use strict';
  let printNumTwo;
  for (let i = 0; i < 3; i++) {
    if (i === 2) {
      printNumTwo = function() {
        return i;
      };
    }
  }
  console.log(printNumTwo());
  // returns 2
  console.log(i);
  // returns "i is not defined"
  1. let聲明不存在變量提升

所謂變量提升,就是之前我們在使用var聲明變量時,變量可以放在聲明之前使用,只不過使用還沒有聲明的變量時,其值為undefined。但是使用let聲明變量時,如果使用放在聲明之前則會報(bào)錯。

  console.log(a); //輸出 undefined
  var a = 1;

  console.log(b); //報(bào)錯
  let b = 1;     

const 命令

const除了擁有let的所有優(yōu)秀特性(不允許重復(fù)聲明,有用塊級作用域)之外,還有一個特性,那就是它是只讀的。


const 實(shí)際上保證的,并不是變量的值不得改動,而是變量指向的那個內(nèi)存地址不得改動。對于簡單類型的數(shù)據(jù)(數(shù)值、字符串、布爾值),值就保存在變量指向的那個內(nèi)存地址,因此等同于常量。但對于復(fù)合類型的數(shù)據(jù)(主要是對象和數(shù)組),變量指向的內(nèi)存地址,保存的只是一個指針, const 只能保證這個指針是固定的,至于它指向的數(shù)據(jù)結(jié)構(gòu)是不是可變的,就完全不能控制了。”

《ES6標(biāo)準(zhǔn)入門》 阮一峰


阮大佬上面這段話具體是什么意思呢,請看下面這個例子:

  "use strict";
  const s = [5, 6, 7];
  s = [1, 2, 3]; // 報(bào)錯
  s[2] = 45; // 正常工作
  console.log(s); // returns [5, 6, 45]

我們將一個新數(shù)組[1, 2, 3]賦值給變量s時,其實(shí)是企圖改變變量s內(nèi)指針的指向,而因?yàn)樽兞?code>s是使用const命令聲明的,其指針指向是固定的,不能變動的,所以程序報(bào)錯。第二次,我們想修改數(shù)組中第二項(xiàng)的值,因?yàn)樾薷臄?shù)組中某一項(xiàng)的值并不改變數(shù)組的地址,變量s內(nèi)所保存的指針依舊指向原來的地址,所以程序可以成功執(zhí)行。

Object.freeze

因?yàn)?code>const并不能保證復(fù)合類型的數(shù)據(jù)是不可改變的,所以我們需要一個新的命令來保證復(fù)合類型的只讀性,這個命令就是Object.freeze,具體用法請看下例:

  let person = {
    name:"XiaoMing",
    review:"yes"
  };
  Object.freeze(person);
  person.review = "no"; //這條命令將會被忽略,因?yàn)榇藭rperson對象是只讀的
  person.newProp = "age"; // 這條命令也將會被忽略
  console.log(obj); 
  // { name: "XiaoMing", review:"yes"}

箭頭函數(shù) (Arrow Functions)

ES6 為我們帶來了一種更簡潔的書寫函數(shù)的方式,箭頭函數(shù)。在舊的標(biāo)準(zhǔn)中,我們是這樣書寫函數(shù)的:

  const myFunc = function() {
    const myVar = "value";
    return myVar;
  }

使用剪頭函數(shù),我們可以將其簡化為:

  const myFunc = () => {
    const myVar = "value";
    return myVar;
  }

還可以進(jìn)一步簡化,我們可以甚至連return都不要:

  const myFunc = () => "value"

箭頭函數(shù)可以傳參:

  // 將輸入的數(shù)乘以2,并返回
  const doubler = (item) => item * 2;

箭頭函數(shù)可以極大的化簡高階函數(shù)的使用。所謂高階函數(shù),就是那些接受一個函數(shù)作為參數(shù)的函數(shù),常見的有:map(),filter()reduce()。在以前我們是這么寫高階函數(shù)的:

  FBPosts.filter(function(post) {
    return post.thumbnail !== null && post.shares > 100 && post.likes > 500;
  })

利用箭頭函數(shù)可以化簡為一行:

FBPosts.filter((post) => post.thumbnail !== null && post.shares > 100 && post.likes > 500)

為函數(shù)的參數(shù)設(shè)置默認(rèn)值

ES6中,你可以為函數(shù)的參數(shù)設(shè)置默認(rèn)值:

  function greeting(name = "Anonymous") {
    return "Hello " + name;
  }
  console.log(greeting("John")); // 輸出 Hello John
  console.log(greeting()); // 輸出 Hello Anonymous

參數(shù)name的默認(rèn)值被設(shè)置為"Anonymous",所以在不傳參直接調(diào)用greeting()時,輸出的是Hello Anonymous。

rest 參數(shù) (Rest Operator)

ES6中引入了rest參數(shù),其形式為...變量名。通過使用rest參數(shù),你可以向函數(shù)傳入不同數(shù)量的參數(shù):

  function howMany(...args) {
    return "You have passed " + args.length + " arguments.";
  }
  console.log(howMany(0, 1, 2)); // 傳入三個參數(shù)
  console.log(howMany("string", null, [1, 2, 3], { })); // 傳入四個參數(shù)

rest參數(shù)中的變量代表一個數(shù)組,所有數(shù)組特有的方法都可以用于這個變量:

  function push(array, ...items) {
    items.forEach(function(item) {
      array.push(item);
      console.log(item);
    });
  }
  var a = [];
  push(a, 1, 2, 3)
  console.log(a)  //輸出 [1, 2, 3]

rest參數(shù)之后不能再有其他參數(shù),否則程序會報(bào)錯。

擴(kuò)展運(yùn)算符 (Spread Operator)

擴(kuò)展運(yùn)算符其實(shí)就是rest參數(shù)中的那三個點(diǎn)...,其作用是將數(shù)組打散:

  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>]

在之前,如果我們想求數(shù)組中的最大值需要這樣寫:

  var arr = [6, 89, 3, 45];
  var maximus = Math.max.apply(null, arr); // 返回 89

因?yàn)?code>Math.max()方法只接受由逗號分隔的參數(shù)序列,比如Math.max(1, 2, 3),所以我們需要apply()進(jìn)行轉(zhuǎn)化。在ES6中,我們不再需要apply()方法,而是可以直接利用擴(kuò)展運(yùn)算符,其形式更易于理解:

  const arr = [6, 89, 3, 45];
  const maximus = Math.max(...arr); // 返回 89

請注意,擴(kuò)展運(yùn)算符...只在某些特定的情況下才可以使用,比如函數(shù)的參數(shù)中,或者數(shù)組中。裸用擴(kuò)展運(yùn)算符程序會報(bào)錯:

  var arr = [6, 89, 3, 45]
  const spreaded = ...arr; //報(bào)錯

解構(gòu)賦值(Destructuring Assignment)

我們已經(jīng)看過了擴(kuò)展運(yùn)算符可以讓我們的數(shù)組操作變得多么高效。對于操作對象,ES6也給出了相似的方法。

  1. 請看下面這個ES5的例子:
  var voxel = {x: 3.6, y: 7.4, z: 6.54 };
  var x = voxel.x; // x = 3.6
  var y = voxel.y; // y = 7.4
  var z = voxel.z; // z = 6.54

ES6中,我們可以這樣做:

  const { x, y, z } = voxel; // x = 3.6, y = 7.4, z = 6.54

如果你想賦值的變量與對象的屬性有不同的名稱,你可以這樣做:

  const { x : a, y : b, z : c } = voxel // a = 3.6, b = 7.4, c = 6.54

以上操作方法被我們稱為解構(gòu)賦值。

  1. 解構(gòu)賦值也可以作用于嵌套的對象:
  const a = {
    start: { x: 5, y: 6},
    end: { x: 6, y: -9 }
  };
  const { start : { x: startX, y: startY }} = a;
  console.log(startX, startY); // 5, 6

  1. 利用解構(gòu)賦值,我們可以輕易的獲取數(shù)組的特定元素:
  const [a, b] = [1, 2, 3, 4, 5, 6];
  console.log(a, b); // 1, 2

  const [a, b,,, c] = [1, 2, 3, 4, 5, 6];
  console.log(a, b, c); // 1, 2, 5
  1. 解構(gòu)賦值可以搭配擴(kuò)展運(yùn)算符使用
  const [a, b, ...arr] = [1, 2, 3, 4, 5, 7];
  console.log(a, b); // 1, 2
  console.log(arr); // [3, 4, 5, 7]

  1. 如果你想將一個對象當(dāng)參數(shù)傳入,你可能會想到這樣做:
  const profileUpdate = (profileData) => {
    const { name, age, nationality, location } = profileData;
    // 函數(shù)操作
  }

但其實(shí)你可以這樣:

  const profileUpdate = ({ name, age, nationality, location }) => {
    // 函數(shù)操作
  }

這樣做的好處是,我們不用把整個對象都傳進(jìn)來,只需要傳入我們需要的那部分。

模板字符串 (Template String)

ES6中引入了一種更強(qiáng)大的字符串寫法,被稱為模板字符串,用反引號( ` )標(biāo)識,用法如下:

  const person = {
    name: "Zodiac Hasbro",
    age: 56
  };

  //用模板字符串方式書寫的字符串,并將其賦給greeting變量
  const greeting = `Hello, my name is ${person.name}!
  I am ${person.age} years old.`;

  console.log(greeting); 
  // 輸出:
  // Hello, my name is Zodiac Hasbro!
  // I am 56 years old.

在上面這段代碼中,有三個地方需要我們注意:

  1. 模板字符串的標(biāo)識符是反引號(`) 而不是單引號(')
  2. 輸出的字符串是多行的,我們在也不需要\n
  3. 語法${}可以用來獲取變量,化簡了之前用+來進(jìn)行字符串拼接的寫法

更簡潔的定義對象的方法

ES5中我們是這樣定義對象的方法的:

  const person = {
    name: "Taylor",
    sayHello: function() {
      return `Hello! My name is ${this.name}.`;
    }
  };

ES6中,我們可以將function關(guān)鍵詞省略:

  const person = {
    name: "Taylor",
    sayHello() {
      return `Hello! My name is ${this.name}.`;
    }
  };

class

ES6中提供了一種新的語法創(chuàng)建對象,即使用class關(guān)鍵詞。需要注意的是,這里的class關(guān)鍵詞只是語法糖,并不具有像傳統(tǒng)的面向?qū)ο蟮恼Z言那樣的特性。

ES5中,我們通常是這樣創(chuàng)建構(gòu)造函數(shù)的:

  var Person = function(name){
    this.name = name;
  }
  var person1 = new Person('Jim');

利用class語法糖,我們可以這樣寫:

  class Person {
    constructor(name){
      this.name = name;
    }
  }
  const person1 = new Person('Jim');

在由class定義的對象中,我們添加了構(gòu)造函數(shù)constructor(),構(gòu)造函數(shù)在new被調(diào)用時喚醒,創(chuàng)建一個新的對象。

用取值函數(shù)和存值函數(shù)(getters and setters)來封裝對象

在由class定義的對象中,存值函數(shù)和取值函數(shù)現(xiàn)在有了自己的關(guān)鍵字getset,用法也更加簡單:

  class Book {
    constructor(author) {
      this._author = author;
    }
    // getter
    get writer(){
      return this._author;
    }
    // setter
    set writer(updatedAuthor){
      this._author = updatedAuthor;
    }
  }
  const lol = new Book('anonymous');
  console.log(lol.writer);  // anonymous
  lol.writer = 'wut';
  console.log(lol.writer);  // wut

請注意我們調(diào)用存值函數(shù)和取值函數(shù)的方式:lol.writer。這種調(diào)用方式讓他們看起來并不像是函數(shù)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容