ES6核心知識總結

嘟嘟俠發表於2018-08-11

一、let和const命令

let不存在變數提升

var命令會發生”變數提升“現象,即變數可以在宣告之前使用,值為undefined。let命令改變了語法行為

    // var 的情況
    console.log(foo); // 輸出undefined
    var foo = 2;

    // let 的情況
    console.log(bar); // 報錯ReferenceError
    let bar = 2;
複製程式碼

let會形成塊級作用域

一般認為塊級作用域就是使用{}包起來的塊。變數只在這個塊裡起作用

    {
        let a = 1;
    }
    console.log(a);// 報錯,a is not defined
複製程式碼

塊級作用域的出現,實際上使得獲得廣泛應用的立即執行函式表示式(IIFE)不再必要了,來,說一道面試題

    var funcs = []
    for (var i = 0; i < 10; i++) {
        funcs.push(function() { console.log(i) })
    }
    funcs.forEach(function(func) {
        func()
    })
複製程式碼

這樣的面試題是大家很常見,很多同學一看就知道輸出十次10 但是如果我們想依次輸出0到9呢?

    // 再來看看es6怎麼處理的
    const funcs = []
    for (let i = 0; i < 10; i++) {
        funcs.push(function() {
            console.log(i)
        })
    }
    funcs.forEach(function(func) {
        func()
    })
複製程式碼

達到相同的效果,ES6 簡潔的解決方案是不是更讓你心動!!!

暫時性死區

只要塊級作用域記憶體在let命令,它所宣告的變數就“繫結”(binding)這個區域,不再受外部的影響,在程式碼塊內,使用let命令宣告變數之前,該變數都是不可用的。這在語法上,稱為“暫時性死區”簡稱 TDZ

    if (true) {
     // TDZ開始
     tmp = 'abc'; // ReferenceError
     console.log(tmp); // ReferenceError

     let tmp; // TDZ結束
     console.log(tmp); // undefined

     tmp = 123;
     console.log(tmp); // 123
    }
複製程式碼

不允許重複宣告

let不允許在相同作用域內,重複宣告同一個變數

    // 報錯
    function func() {
     let a = 10;
      var a = 1;
    }

    // 報錯
    function func() {
     let a = 10;
     let a = 1;
    }
複製程式碼

const基本用法

const宣告一個只讀的常量。一旦宣告,常量的值就不能改變,

    const PI = 3.1415;
    PI // 3.1415

    PI = 3;
    // TypeError: Assignment to constant variable.
複製程式碼

我們通常用 let 和 const 來宣告,let 表示變數、const 表示常量。const的作用域與let命令相同:只在宣告所在的塊級作用域內有效,const命令宣告的常量也是不提升,同樣存在暫時性死區,只能在宣告的位置後面使用,const宣告的常量,也與let一樣不可重複宣告。

const本質

const實際上保證的,並不是變數的值不得改動,而是變數指向的那個記憶體地址所儲存的資料不得改動。

    const a = [];
    a.push('Hello'); // 可執行
    a.length = 0;    // 可執行
    a = ['Dave'];    // 報錯
複製程式碼

上面程式碼中,常量a儲存的是一個地址,這個地址指向一個陣列。不可變的只是這個地址,即不能把a指向另一個地址,但陣列本身是可變的,如果將另一個陣列賦值給a,就會報錯。

二、變數的解構賦值

陣列的解構賦值

本質上,這種寫法屬於“模式匹配”,只要等號兩邊的模式相同,左邊的變數就會被賦予對應的值

let [foo, [[bar], baz]] = [1, [[2], 3]];
foo // 1
bar // 2
baz // 3

let [ , , third] = ["foo", "bar", "baz"];
third // "baz"

let [x, , y] = [1, 2, 3];
x // 1
y // 3
複製程式碼

解構賦值允許指定預設值.

let [x, y = 'b'] = ['a']; // x='a', y='b'
複製程式碼

如果解構不成功,變數的值就等於undefined。

let [foo] = [];
let [bar, foo] = [1];
複製程式碼

物件的解構賦值

解構不僅可以用於陣列,還可以用於物件。

let { foo, bar } = { foo: "aaa", bar: "bbb" };
foo // "aaa"
bar // "bbb"
複製程式碼

字串的解構賦值

字串也可以解構賦值。這是因為此時,字串被轉換成了一個類似陣列的物件。

const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"
複製程式碼

解構賦值的用途

(1)交換變數的值

let x = 1;
let y = 2;

[x, y] = [y, x];
複製程式碼

(2)從函式返回多個值

// 返回一個陣列
function example() {
  return [1, 2, 3];
}
let [a, b, c] = example();

// 返回一個物件
function example() {
  return {
    foo: 1,
    bar: 2
  };
}
let { foo, bar } = example();
複製程式碼

三、模板字串

模板字串使用十分方便,經常用於輸出一個結果。舉個例子

var name = "小強"
console.log("我的名字叫"+name)
//模板字串表達
console.log(`我的名字叫${name}`)
複製程式碼

四、箭頭函式

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

var f = function (v) {
  return v*v;
};
//轉化為箭頭函式如下
var f = (v)=>{
    return v*v;
}
//當你的函式有且僅有一個引數的時候,是可以省略掉括號的。當你函式返回有且僅有一個表示式的時候可以省略{} 和 return
var f = v => v*v;
複製程式碼

五、陣列的擴充套件

擴充套件運算子

擴充套件運算子(spread)是三個點(...)。它好比 rest 引數的逆運算,將一個陣列轉為用逗號分隔的引數序列。

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

console.log(1, ...[2, 3, 4], 5)
// 1 2 3 4 5
複製程式碼

擴充套件運算子的應用

(1)複製陣列 (注意:使用擴充套件運算子複製一個陣列屬於深拷貝,兩個陣列之間互相獨立,改變其中一個的值不會影響另一個的值)

const a1 = [1, 2];
// 寫法一
const a2 = [...a1];
// 寫法二
const [...a2] = a1;
複製程式碼

(2)合併陣列

const arr1 = ['a', 'b'];
const arr2 = ['c'];
const arr3 = ['d', 'e'];

// ES5 的合併陣列
arr1.concat(arr2, arr3);
// [ 'a', 'b', 'c', 'd', 'e' ]

// ES6 的合併陣列
[...arr1, ...arr2, ...arr3]
// [ 'a', 'b', 'c', 'd', 'e' ]
複製程式碼

(3)與解構賦值結合

const [first, ...rest] = [1, 2, 3, 4, 5];
first // 1
rest  // [2, 3, 4, 5]

const [first, ...rest] = ["foo"];
first  // "foo"
rest   // []
複製程式碼

(4)擴充套件運算子還可以將字串轉為真正的陣列

[...'hello']
// [ "h", "e", "l", "l", "o" ]
複製程式碼

Array.from()

Array.from方法用於將兩類物件轉為真正的陣列:類似陣列的物件(array-like object)和可遍歷(iterable)的物件

let arrayLike = {
    '0': 'a',
    '1': 'b',
    '2': 'c',
    length: 3
};

// ES5的寫法
var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']

// ES6的寫法
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']
複製程式碼

值得提醒的是,擴充套件運算子(...)也可以將某些資料結構轉為陣列。

Array.of()

Array.of方法用於將一組值,轉換為陣列。

Array.of(3, 11, 8) // [3,11,8]
Array.of(3) // [3]
Array.of(3).length // 1
複製程式碼

這個方法的主要目的,是彌補陣列建構函式Array()的不足。因為引數個數的不同,會導致Array()的行為有差異。

陣列例項的 find() 和 findIndex()

陣列例項的find方法,用於找出第一個符合條件的陣列成員。它的引數是一個回撥函式,所有陣列成員依次執行該回撥函式,直到找出第一個返回值為true的成員,然後返回該成員。如果沒有符合條件的成員,則返回undefined。

[1, 4, -5, 10].find((n) => n < 0)
// -5
複製程式碼

陣列例項的findIndex方法的用法與find方法非常類似,返回第一個符合條件的陣列成員的位置,如果所有成員都不符合條件,則返回-1。

[1, 5, 10, 15].findIndex(function(value, index, arr) {
  return value > 9;
}) // 2
複製程式碼

陣列例項的 fill()

fill方法使用給定值,填充一個陣列。

['a', 'b', 'c'].fill(7)
// [7, 7, 7]

new Array(3).fill(7)
// [7, 7, 7]
複製程式碼

fill方法還可以接受第二個和第三個引數,用於指定填充的起始位置和結束位置

['a', 'b', 'c'].fill(7, 1, 2)
// ['a', 7, 'c']
複製程式碼

上面程式碼表示,fill方法從 1 號位開始,向原陣列填充 7,到 2 號位之前結束。

陣列例項的 includes()

Array.prototype.includes方法返回一個布林值,表示某個陣列是否包含給定的值,與字串的includes方法類似。

[1, 2, 3].includes(2)     // true
[1, 2, 3].includes(4)     // false
[1, 2, NaN].includes(NaN) // true
複製程式碼

六、class

class建立類

(1)class 是關鍵字,後面緊跟類名,類名首字母大寫,採取的是大駝峰命名法則。類名之後是{}。

(2)在{}中,不能直接寫語句,只能寫方法,方法不需要使用關鍵字

(3)方法和方法之間沒有逗號。不是鍵值對

舉個栗子:

class NBAPlayer{
    constructor(name,age,height){
        this.name = name
        this.age = age
        this.height = height
    }
    say(){
        console.log(`我是${this.name},我今年${this.age},我的身高${this.height}`)
    }
}
var rs = new NBAPlayer("姚明","35","226")
rs.say()
複製程式碼

使用extends實現繼承

注意:在子類中的構造器 constructor 中,必須要顯式呼叫父類的 super 方法,如果不呼叫,則 this 不可用

class NBAPlayer{
    constructor(name,age,height){
        this.name = name
        this.age = age
        this.height = height
    }
    say(){
        console.log(`我是${this.name},我今年${this.age},我的身高${this.height}`)
    }
}
class MVP extends NBAPlayer{
    constructor(name,age,height,year){
        super(name,age,height)
        this.year = year
    }
    sayi(){
        console.log(`我是${this.name},我在${this.year}拿MVP`)
    }
}
var rs = new MVP("姚明","35","226","2014")
rs.say()
rs.sayi()
複製程式碼

七、set和map

(1)set

set和陣列差不多,也是一種集合,區別在於:它裡面的值都是唯一的,沒有重複的。Set 本身是一個建構函式,用來生成 Set 資料結構。

const s = new Set();

[2, 3, 5, 4, 5, 2, 2].forEach(x => s.add(x));

for (let i of s) {
  console.log(i);
}
// 2 3 5 4
複製程式碼

上面程式碼通過add方法向 Set 結構加入成員,結果表明 Set 結構不會新增重複的值。for of 一種遍歷方式

// 去除陣列的重複成員
[...new Set(array)]
複製程式碼

(2)map

它類似於物件,裡面存放也是鍵值對,區別在於:物件中的鍵名只能是字串,如果使用map,它裡面的鍵可以是任意值。

const m = new Map();
const o = {p: 'Hello World'};

m.set(o, 'content')
m.get(o) // "content"

m.has(o) // true
m.delete(o) // true
m.has(o) // false
複製程式碼

上面程式碼使用 Map 結構的set方法,將物件o當作m的一個鍵,然後又使用get方法讀取這個鍵,接著使用delete方法刪除了這個鍵

const map = new Map([
  ['name', '張三'],
  ['title', 'Author']
]);

map.size // 2
map.has('name') // true
map.get('name') // "張三"
map.has('title') // true
map.get('title') // "Author"
複製程式碼

作為建構函式,Map 也可以接受一個陣列作為引數。該陣列的成員是一個個表示鍵值對的陣列。

八、嚴格模式

JS語法非常靈活,JS中這個靈活的特性,弊大於先利。後來增加了嚴格模式。使用嚴格模式的目的:規則,提高編譯效率。

怎麼去啟動嚴格模式: "use strict"

嚴格模式和非嚴格模式有什麼區別:

1.在嚴格模式下不能使用沒有var的變數

2.在嚴格模式下不能8進位制的數字

3.在嚴格模式下不能把函式定義在if語句中

4.在嚴格模式下函式不能有重名的形參

5.在嚴格模式下不能arguments就不能使用了

6.在嚴格模式下不能function中的this就再在是window

初學ES6,文章有誤請指點,文內部分用詞不準確也請諒解

相關文章