ES6背記手冊


如下內容大部分參考自阮一峯的ES6在線教程javascript

ES6新特性一覽

  • letconst
  • 暫時性死區
  • 解構賦值
  • 字符串的unicode表示
  • 模板字符串
  • 對象簡寫屬性
  • 函數的默認參數
  • 函數的剩餘參數(rest參數)
  • spread操做符
  • 箭頭函數
  • 尾調用優化
  • 遍歷器
  • for...of...
  • Symbol
  • Map和Set
  • class
  • Promise
  • Generator
  • async await
  • Proxy和Reflect
  • 二進制數組
  • 模塊
  • Math、Number、String、Object、RegExp擴展

let和const的異同

相同點html

  • letconst聲明的變量,都是塊級做用域,都只在其所在的代碼塊內有效
  • letconst聲明的變量,都不存在變量提高
  • letconst聲明的變量,都存在臨時性死區
  • letconst都不容許在經過一個做用於內重複聲明同一個變量
  • letconst都不容許在函數內對參數從新聲明
  • letconst聲明的變量,都不是頂層對象的屬性

不一樣點java

  • let聲明的是變量,聲明後,能夠在任意時刻賦值,修改
  • const聲明的是常量,聲明後必須馬上賦值,且之後不容許修改

let和var的異同

相同點react

  • letvar都是聲明一個變量
  • letvar聲明的變量,都是能夠在聲明後,任意時刻賦值,修改

不一樣點git

  • let無變量提高,var有變量提高
  • let是塊級做用域,var是函數級做用域
  • let不可在做用域內重複聲明同一個變量,var能夠在同一個做用域內聲明同一個變量
  • let聲明的變量不屬於頂層對象的屬性,var聲明的變量屬於頂層對象的屬性
  • let存在臨時性死區,var不存在臨時性死區

其餘es6

  1. 在同做用域內,不能同時使用letvar聲明同名變量,無論誰先誰後都不行

const的實質

const實際保證的,並非變量的值不能改動,而是變量指向的那個內存地址所所保存的數據不能改變。github

JavaScript中的簡單類型數據,好比string, number, boolean, null, undefined,值就保存在變量指向的那個內存地址,而複合類型的數據,變量指向的那個內存地址,保存的是指向實際數據的一個指針。編程

什麼是臨時性死區

ES6新概念:臨時性死區——TDZ——Temporal Dead Zonejson

因爲代碼(代碼塊,函數,模塊......)中的變量尚未被初始化而不能使用的狀況,具體表現爲——報錯:Uncaught ReferenceError: xxx is not definedlet,const,class都有臨時性死區的表現。在ES6以前,若是在變量初始化以前使用變量,並不會報錯,只是其值爲undefined而已。數組

模板字符串

  1. 模板字符串簡化了多行字符串的寫法
  2. 模板字符串簡化了在字符串中籤入變量的寫法
  3. 模板字符串中的變量若是沒有聲明的話,會報錯
  4. 模板字符串默認會將字符串轉義

ES6中的函數

  1. 函數參數能夠設置默認值
  2. 函數參數的默認值是惰性求值
  3. 函數參數設置默認值後build影響函數的length屬性:function add(a, b, c=3){} add.length === 2;// true
  4. 在ES6中,若是函數參數使用了默認值、解構賦值、擴展運算符,就不能在函數內部顯式指定爲嚴格模式。函數指定默認值後,顯式添加use strict,報錯:Uncaught SyntaxError: Illegal 'use strict' directive in function with non-simple parameter list
  5. rest參數只能是尾參數
  6. rest參數不計入函數的length屬性
  7. rest參數是一個真正的數組,arguments是類數組
  8. 在ES6中,name屬性會返回實際的函數名

箭頭函數

  1. 函數體內的this就是定義時的對象,而不是使用時的對象
  2. 箭頭函數不能夠當作構造函數
  3. 箭頭函數內部不存在arguments對象,使用...rest參數代替
  4. 箭頭函數不能夠作Generator函數
  5. 箭頭函數沒法使用apply,bind,call改變this指向

解構賦值

可解構賦值的:

  • 數組
  • Set
  • 字符串
  • 對象
  • 函數參數
  1. 數組解構賦值:
// a === 12 
// b === 33
const [a, b] = [12, 33];
  1. 數組解構默認值:
// f === 120 
// h === 56
const [f, h = 100] = [120, 56];
  1. 數組解構默認值:
// f === 120 
// h === 100
const [f, h = 100] = [120, undefined];
  1. 對象解構賦值:
// a === 'Pelli' 
// b === 89
const {a, b} = {a: 'Pelli', b: 89};
  1. 對象解構賦值:
// a === 'pelli 
// b === 18 
// c === 'worker'
const {
    myname: a, 
    age: b, 
    job: c
} = {
    myname: 'pelli', 
    age: 18, 
    job: 'worker'
};
  1. 對象解構默認值:
// p === 'ppp' 
// q === 'hello world'
const {p, q = 'hello world'} = {p: 'ppp', q: 'qqqq'};
  1. 解構賦值的默認值需undefined觸發,
    • 對於數組來講,對應位置沒有元素
    • 對於對象來講,沒有同名屬性
    • 或者將同名屬性或元素顯式賦值爲undefined
  2. 字符串解構賦值:
// a === 'h' 
// b === 'e' 
// c === 'l'
const [a, b, c] = 'hello world';
  1. 函數參數的解構賦值
const args = function(){return arguments;}
const ags = args(3, 4, 5, 6, 12, 2, 3);
// a === 3 
// b === 4 
// c === 5 
// d === 6 
// e === 12
// f = 2
const [a, b, c, d, e, f] = ags;
  1. 解構賦值時,若是等號右邊是數值和布爾值,則會先轉爲對象

解構賦值圓括號

最佳實踐:任什麼時候候都不要在解構賦值中放置圓括號

如下狀況不能使用

  1. 變量聲明語句
  2. 函數參數
  3. 賦值語句模式

只有一種狀況可使用圓括號

  1. 賦值語句的非模式部分

解構賦值使用場景

  1. 變量交換
  2. 從函數返回多個值
  3. 定義函數參數
  4. 提取json數據
  5. 定義函數參數默認值
  6. 遍歷Map結構
  7. 輸入模塊指定方法

Symbol

  1. Symbol不是構造函數,定義一個Symbol,前不用加new,正確使用方式爲: const s = Symbol()
  2. Symbol值做爲對象屬性名時,只能使用[]方式訪問,不能經過點運算符訪問屬性
  3. Symbol是獨一無二的值

Set和Map

  1. Set相似於數組,可是其中的值都是惟一的,不可重複
  2. Set構造函數的參數必須是可遍歷的:arguments,string,array,set,map
  3. Set構造函數的參數只有第一個有效(只須要一個參數)
  4. Set的add方法返回的是Set對象,能夠鏈式調用
  5. Map的set方法,返回的是Map對象,能夠鏈式調用
  6. Set內部只能存在一個NaN
  7. Object.is(0, -0); // false,可是,Set內部0-0相等,只能存在一個.
  8. Set內部:兩個空對象,空數組,空函數老是不相等
  9. Map數據結構是鍵值對的集合
  10. Map數據結構的鍵不只僅能夠是字符串,任何數據類型均可以做爲鍵

for...of...循環

  • arguments
  • 數組
  • 字符串
  • Set
  • Map

Promise的特色

  1. Promise對象的狀態不受外界影響
  2. Promise對象的狀態一旦肯定就不會再改變
  3. Promise對象的狀態變化只多是兩個結果中的一個:接受或拒絕

Promise的缺點

  1. Promise對象一旦建立,就沒法中途取消
  2. 若是不設置回調函數,Promise對象內部拋出的錯誤不會反映到外部
  3. 當Promise對象處於pending時,沒法得知目前的進展在哪個階段,換一種說法是沒法肯定事件的完成度
  4. 代碼冗餘,相對於回調函數來講,語義弱化。無論什麼操做都是一堆then

Promise對象和其餘代碼的執行順序

  1. 當即執行的Promise比外層其餘代碼後執行
  2. 當即執行的Promise比setTimeout 0先執行

Promise自己並非異步的,Promise中的「異步」特性是由resolve或者reject的執行時機帶來的

// 下面幾行代碼輸出順序爲:3,2,1
setTimeout(() => {
    console.log('1');
}, 0);

var p = new Promise((resolve, reject) => {
    resolve('2')
});

p.then((val) => {
    console.log(val, 'promise');
})

console.log('3');

另外的幾行代碼:

// 下面幾行代碼輸出順序爲:3,1,2
setTimeout(() => {
    console.log('1');
}, 0);

var p = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('2')
    }, 0);
});

p.then((val) => {
    console.log(val, 'promise');
})

console.log('3');

Promise對象的寫法最佳實踐

參考來源:http://es6.ruanyifeng.com/#docs/promise

理由是下面這種寫法能夠捕獲前面then方法執行中的錯誤(也就是說,catch不只能夠捕獲到promise被拒絕的狀態,也能夠捕獲前面then方法中的錯誤),也更接近同步的寫法(try/catch)。所以,建議老是使用catch方法,而不使用then方法的第二個參數。

p.then(function(val){}).catch(function(msg){})的寫法

var p = new Promise(function(resolve, reject){
    setTimeout(function(){
        var status = Math.random() * 10;

        if(status > 5){
            resolve(status);
        }else{
            reject('失敗');
        }
    }, 10000);
});

p.then(function(value){
    console.log(value);
}).catch(function(msg){
    console.log(msg);
});

不推薦的寫法以下:

then方法傳遞兩個參數,第二參數是當被拒絕的時候執行的函數

var p = new Promise(function(resolve, reject){
    setTimeout(function(){
        var status = Math.random() * 10;

        if(status > 5){
            resolve(status);
        }else{
            reject('失敗');
        }
    }, 10000);
});

p.then(function(value){
    console.log(value);
}, function(msg){
    // 這裏只有在promise被拒絕的時候纔會執行
    // 若是then方法報錯了,這裏沒法獲知
    console.log(msg);
});

Promise的其餘一些常識

  • Promise不能直接作函數調用,即不能:Promise()

class的一些常識

  • class能夠看作是語法糖,只是讓對象原型的寫法更加清晰,更像面向對象的編程語言
  • 類的數據類型是函數,類自己指向構造函數
  • 類不能作函數直接調用,必須和new一塊兒使用
  • 類沒有變量提高
  • 類的全部方法都定義在prototype上面
  • 類內部定義的全部屬性都是不可枚舉的
  • 類的length屬性值是constructor的參數個數(不包括有默認值的參數)

ES6中的NaN

  1. Number擴展,Number.isNaN()
  2. ES6中,window的方法isNaN()是爲了保證向下兼容性,在ES6中,建議使用Nunber.isNaN()
  3. Object.is()中,NaNNaN是相等的,Object.is(NaN, NaN) === true
  4. Set中,只容許存在一個NaN

ES6中的模塊

  • 模塊相關名詞:CommonJSAMDCMDUMD,ES6 Module
  • ES6以前的模塊規範:CommonJSAMD,CommonJS用於服務器,AMD用於瀏覽器
  • ES6的模塊設計思想是儘可能靜態化,使得在編譯時就能肯定模塊的依賴關係以及輸入輸出的變量
  • CommonJSAMD模塊,都只能在運行時肯定這些東西,好比,CommonJS模塊就是對象,輸入時必須查找對象屬性
  • ES6模塊是編譯時加載,使得靜態分析成爲可能
  • ES6模塊自動採用嚴格模式,無論有沒有顯式聲明"use strict;"
  • 在ES6模塊中,頂層的this指向undefined
  • 若是A模塊引入的模塊B是基本類型,A對B從新賦值的話會報錯,若是B是引用類型,A對其屬性從新賦值, B的屬性值會改變,若是別的模塊(好比C模塊)也引用了B模塊,則A對B的屬性值修改也會體如今C模塊中
  • 最佳實踐:不要對引入的模塊進行修改
  • 模塊中的import有提高效果,會提高到整個模塊以前。提高效果的實質是:import命令是編譯階段執行的,編譯階段老是在代碼實際運行以前
  • 因爲import是靜態執行的,不能使用表達式和變量,由於表達式和變量只有在運行時才能獲取到結果
  • 若是屢次執行同一條import語句,則只會真正執行一次,不會執行屢次
  • ES6模塊中的幾個關鍵語句:import 'react';,import {lodash} from 'lodash';, , import * from 'react', export var a = 12;, const a = 55; export default a;
  • 正是由於export default其實是輸出一個名爲default的變量,因此不能在export default後面加變量聲明語句
  • ES6模塊沒法動態加載、按條件加載、運行時加載。由於import語句是在編譯時執行的,是靜態的

CommonJS和ES6模塊的不一樣

  • CommonJS 模塊輸出的是一個值的拷貝,ES6 模塊輸出的是值的引用。
  • CommonJS 模塊是運行時加載,ES6 模塊是編譯時輸出接口。
  • Node環境中,ES6 模塊之中,頂層的this指向undefinedCommonJS 模塊的頂層this指向當前模塊,這是二者的一個重大差別。
  • 在Node環境中,如下幾個變量在模塊中是不存在的:arguments,require,module,exports,__filename,__dirname

ES6模塊的運行機制

ES6 模塊的運行機制與 CommonJS 不同。JS 引擎對腳本靜態分析的時候,遇到模塊加載命令import,就會生成一個只讀引用。等到腳本真正執行時,再根據這個只讀引用,到被加載的那個模塊裏面去取值。換句話說,ES6 的import有點像 Unix 系統的「符號鏈接」,原始值變了,import加載的值也會跟着變。所以,ES6 模塊是動態引用,而且不會緩存值,模塊裏面的變量綁定其所在的模塊。


微信公衆號:撩碼

微信公衆號:撩碼

相關文章
相關標籤/搜索