重溫基礎:ES6系列(一)

640?wx_fmt=png

ES6系列目錄

  • 1 let 和 const命令

  • 2 變量的解構賦值

  • 3 字符串的拓展

  • 4 正則的拓展

  • 5 數值的拓展

  • 6 函數的拓展

  • 7 數組的拓展

  • 8 對象的拓展

  • 9 Symbol

  • 10 Set和Map數據結構

  • 11 Proxy

  • 12 Promise對象

  • 13 Iterator和 for...of循環

  • 14 Generator函數和應用

  • 15 Class語法和繼承

  • 16 Module語法和加載實現

所有整理的文章都收錄到我《Cute-JavaScript》系列文章中,訪問地址:http://js.pingan8787.com

1 let 和 const命令

在ES6中,我們通常實用 let 表示變量const 表示常量,並且 letconst 都是塊級作用域,且在當前作用域有效不能重複聲明。

1.1 let 命令

let 命令的用法和 var 相似,但是 let 只在所在代碼塊內有效。基礎用法

{	
    let a = 1;	
    let b = 2;	
}

並且 let 有以下特點:

  • 不存在變量提升:var 聲明一個變量一個函數,都會伴隨着變量提升的問題,導致實際開發過程經常出現一些邏輯上的疑惑,按照一般思維習慣,變量都是需要先聲明後使用。

// var	
console.log(v1); // undefined	
var v1 = 2;	
// 由於變量提升 代碼實際如下	
var v1;	
console.log(v1)	
v1 = 2;	
// let	
console.log(v2); // ReferenceError	
let v2 = 2;
  • 不允許重複聲明:let 和 const 在相同作用域下,都不能重複聲明同一變量,並且不能在函數內重新聲明參數

// 1. 不能重複聲明同一變量	
// 報錯	
function f1 (){	
    let a = 1;	
    var a = 2;	
}	
// 報錯	
function f2 (){	
    let a = 1;	
    let a = 2;	
}	
// 2. 不能在函數內重新聲明參數	
// 報錯	
function f3 (a1){	
    let a1; 	
}	
// 不報錯	
function f4 (a2){	
    {	
        let a2	
    }	
}

1.2 const 命令

const 聲明一個只讀常量基礎用法

const PI = 3.1415926;	
console.log(PI);  // 3.1415926

注意點

  • const 聲明後,無法修改值;

const PI = 3.1415926;	
PI = 3; 	
// TypeError: Assignment to constant variable.
  • const 聲明時,必須賦值;

const a ; 	
// SyntaxError: Missing initializer in const declaration.
  • const 聲明的常量, let 不能重複聲明;

const PI = 3.1415926;	
let PI = 0;  	
// Uncaught SyntaxError: Identifier 'PI' has already been declared

2 變量的解構賦值

解構賦值概念:在ES6中,直接從數組和對象中取值,按照對應位置,賦值給變量的操作。

2.1 數組

基礎用法

// ES6 之前	
let a = 1;	
let b = 2;	
// ES6 之後	
let [a, b] = [1, 2];

本質上,只要等號兩邊模式一致,左邊變量即可獲取右邊對應位置的值,更多用法:

let [a, [[b], c]] = [1, [[2], 3]];	
console.log(a, b, c); // 1, 2, 3	
let [ , , c] = [1, 2, 3];	
console.log(c);       // 3	
let [a, , c] = [1, 2, 3];	
console.log(a,c);     // 1, 3	
let [a, ...b] = [1, 2, 3];	
console.log(a,b);     // 1, [2,3]	
let [a, b, ..c.] = [1];	
console.log(a, b, c); // 1, undefined, []

注意點

  • 如果解構不成功,變量的值就等於 undefined

let [a] = [];     // a => undefined	
let [a, b] = [1]; // a => 1 , b => undefined
  • 當左邊模式多於右邊,也可以解構成功。

let [a, b] = [1, 2, 3];	
console.log(a, b); // 1, 2
  • 兩邊模式不同,報錯。

let [a] = 1;	
let [a] = false;	
let [a] = NaN;	
let [a] = undefined;	
let [a] = null;	
let [a] = {};

指定解構的默認值基礎用法

let [a = 1] = [];      // a => 1	
let [a, b = 2] = [a];  // a => 1 , b => 2

特殊情況:

let [a = 1] = [undefined]; // a => 1	
let [a = 1] = [null];      // a => null

右邊模式對應的值,必須嚴格等於 undefined,默認值才能生效,而 null不嚴格等於 undefined

2.2 對象的解構賦值

與數組解構不同的是,對象解構不需要嚴格按照順序取值,而只要按照變量名去取對應屬性名的值,若取不到對應屬性名的值,則爲 undefined

基礎用法

let {a, b} = {a:1, b:2};  // a => 1 , b => 2	
let {a, b} = {a:2, b:1};  // a => 2 , b => 1	
let {a} = {a:3, b:2, c:1};// a => 3	
let {a} = {b:2, c:1};     // a => undefined

注意點

  • 變量名屬性名不一致,則需要修改名稱。

let {a:b} = {a:1, c:2}; 	
// error: a is not defined	
// b => 1

對象的解構賦值的內部機制,是先找到同名屬性,然後再賦給對應的變量。真正被賦值的是後者,而不是前者。a 是匹配的模式, b纔是變量。真正被賦值的是變量 b,而不是模式 a

  • 對象解構也支持嵌套解構

let obj = {	
    a:[ 1, { b: 2}]	
};	
let {a, a: [c, {b}]} = obj;	
// a=>[1, {b: 2}], b => 2, c => 1

指定解構的默認值

let {a=1} = {};        // a => 1	
let {a, b=1} = {a:2};  // a => 2, b => 1	
let {a:b=3} = {};      // b => 3	
let {a:b=3} = {a:4};   // b = >4	
// a是模式,b是變量 牢記	
let {a=1} = {a:undefined};  // a => 1	
let {a=1} = {a:null};   // a => null	
// 因爲null與undefined不嚴格相等,所以賦值有效	
// 導致默認值1不會生效。

2.3 字符串的解構賦值

字符串的解構賦值中,字符串被轉換成了一個類似數組的對象基礎用法

const [a, b, c, d, e] = 'hello';	
a // "h"	
b // "e"	
c // "l"	
d // "l"	
e // "o"	
let {length:len} = 'hello';// len => 5

2.4 數值和布爾值的解構賦值

解構賦值的規則是,只要等號右邊的值不是對象或數組,就先將其轉爲對象。由於 undefinednull無法轉爲對象,所以對它們進行解構賦值,都會報錯。

// 數值和布爾值的包裝對象都有toString屬性	
let {toString: s} = 123;	
s === Number.prototype.toString // true	
let {toString: s} = true;	
s === Boolean.prototype.toString // true	
let { prop: x } = undefined; // TypeError	
let { prop: y } = null;      // TypeError

2.5 函數參數的解構賦值

基礎用法

function fun ([a, b]){	
    return a + b;	
}	
fun ([1, 2]); // 3

指定默認值的解構:

function fun ({a=0, b=0} = {}){	
    return [a, b];	
}	
fun ({a:1, b:2}); // [1, 2]	
fun ({a:1});      // [1, 0]	
fun ({});         // [0, 0]	
fun ();           // [0, 0]	
function fun ({a, b} = {a:0, b:0}){	
    return [a, b];	
}	
fun ({a:1, b:2}); // [1, 2]	
fun ({a:1});      // [1, undefined]	
fun ({});         // [undefined, undefined]	
fun ();           // [0, 0]

2.6 應用

  • 交換變量的值:

let a = 1,b = 2;	
[a, b] = [b, a]; // a =>2 , b => 1
  • 函數返回多個值:

// 返回一個數組	
function f (){	
    return [1, 2, 3];	
}	
let [a, b, c] = f(); // a=>1, b=>2, c=>3	
// 返回一個對象	
function f (){	
    return {a:1, b:2};	
}	
let {a, b} = f();    // a=>1, b=>2
  • 快速對應參數: 快速的將一組參數與變量名對應。

function f([a, b, c]) {...}	
f([1, 2, 3]);	
function f({a, b, c}) {...}	
f({b:2, c:3, a:1});
  • 提取JSON數據

let json = {	
    name : 'leo',	
    age: 18	
}	
let {name, age} = json;	
console.log(name,age); // leo, 18
  • 遍歷Map結構:

const m = new Map();	
m.set('a', 1);	
m.set('b', 2);	
for (let [k, v] of m){	
    console.log(k + ' : ' + v);	
}	
// 獲取鍵名	
for (let [k] of m){...}	
// 獲取鍵值	
for (let [,k] of m){...}
  • 輸入模塊的指定方法: 用於按需加載模塊中需要用到的方法。

const {log, sin, cos} = require('math');

3 字符串的拓展

3.1 includes(),startsWith(),endsWith()

在我們判斷字符串是否包含另一個字符串時,ES6之前,我們只有 typeof方法,ES6之後我們又多了三種方法:

  • includes():返回布爾值,表示是否找到參數字符串

  • startsWith():返回布爾值,表示參數字符串是否在原字符串的頭部

  • endsWith():返回布爾值,表示參數字符串是否在原字符串的尾部

let a = 'hello leo';	
a.startsWith('leo');   // false	
a.endsWith('o');       // true	
a.includes('lo');      // true

並且這三個方法都支持第二個參數,表示起始搜索的位置。

let a = 'hello leo';	
a.startsWith('leo',1);   // false	
a.endsWith('o',5);       // true	
a.includes('lo',6);      // false

endsWith 是針對前 n 個字符,而其他兩個是針對從第 n個位置直到結束。

3.2 repeat()

repeat方法返回一個新字符串,表示將原字符串重複 n次。基礎用法

'ab'.repeat(3);        // 'ababab'	
'ab'.repeat(0);        // ''

特殊用法:

  • 參數爲 小數,則取整

'ab'.repeat(2.3);      // 'abab'
  • 參數爲 負數或 Infinity,則報錯

'ab'.repeat(-1);       // RangeError	
'ab'.repeat(Infinity); // RangeError
  • 參數爲 0到-1的小數或 NaN,則取0

'ab'.repeat(-0.5);     // ''	
'ab'.repeat(NaN);      // ''
  • 參數爲 字符串,則轉成 數字

'ab'.repeat('ab');     // ''	
'ab'.repeat('3');      // 'ababab'

3.3 padStart(),padEnd()

用於將字符串頭部尾部補全長度, padStart()頭部補全padEnd()尾部補全2個參數,第一個指定字符串最小長度,第二個用於補全的字符串基礎用法

'x'.padStart(5, 'ab');   // 'ababx'	
'x'.padEnd(5, 'ab');     // 'xabab'

特殊用法:

  • 原字符串長度,大於或等於指定最小長度,則返回原字符串。

'xyzabc'.padStart(5, 'ab'); // 'xyzabc'
  • 用來補全的字符串長度和原字符串長度之和,超過指定最小長度,則截去超出部分的補全字符串。

'ab'.padStart(5,'012345'); // "012ab"
  • 省略第二個參數,則用 空格補全。

'x'.padStart(4);           // '    x'	
'x'.padEnd(4);             // 'x    '

3.4 模版字符串

用於拼接字符串,ES6之前:

let a = 'abc' + 	
    'def' + 	
    'ghi';

ES6之後:

let a = `	
    abc	
    def	
    ghi	
`

拼接變量: 在反引號(`)中使用 ${}包裹變量或方法。

// ES6之前	
let a = 'abc' + v1 + 'def';	
// ES6之後	
let a = `abc${v1}def`

4 正則的拓展

4.1 介紹

在ES5中有兩種情況。

  • 參數是字符串,則第二個參數爲正則表達式的修飾符。

let a = new RegExp('abc', 'i');	
// 等價於	
let a = /abx/i;
  • 參數是正則表達式,返回一個原表達式的拷貝,且不能有第二個參數,否則報錯。

let a = new RegExp(/abc/i);	
//等價於	
let a = /abx/i;	
let a = new RegExp(/abc/, 'i');	
//  Uncaught TypeError

ES6中使用:

new RegExp(/abc/ig, 'i');

4.2 字符串的正則方法

常用的四種方法:match()replace()search()split()

4.3 u修飾符

添加 u修飾符,是爲了處理大於 uFFFF的Unicode字符,即正確處理四個字節的UTF-16編碼。

/^\uD83D/u.test('\uD83D\uDC2A'); // false	
/^\uD83D/.test('\uD83D\uDC2A');  // true

由於ES5之前不支持四個字節UTF-16編碼,會識別爲兩個字符,導致第二行輸出 true,加入 u修飾符後ES6就會識別爲一個字符,所以輸出 false

注意:u修飾符後,會改變下面正則表達式的行爲:

  • (1)點字符 點字符( .)在正則中表示除了換行符以外的任意單個字符。對於碼點大於 0xFFFF的Unicode字符,點字符不能識別,必須加上 u修飾符。

var a = "?";	
/^.$/.test(a);  // false	
/^.$/u.test(a); // true
  • (2)Unicode字符表示法 使用ES6新增的大括號表示Unicode字符時,必須在表達式添加 u修飾符,才能識別大括號。

/\u{61}/.test('a');      // false	
/\u{61}/u.test('a');     // true	
/\u{20BB7}/u.test('?'); // true
  • (3)量詞 使用 u修飾符後,所有量詞都會正確識別碼點大於 0xFFFF的 Unicode 字符。

/a{2}/.test('aa');    // true	
/a{2}/u.test('aa');   // true	
/?{2}/.test('??');  // false	
/?{2}/u.test('??'); // true
  • (4)i修飾符 不加 u修飾符,就無法識別非規範的 K字符。

/[a-z]/i.test('\u212A') // false	
/[a-z]/iu.test('\u212A') // true

檢查是否設置 u修飾符:使用 unicode屬性。

const a = /hello/;	
const b = /hello/u;	
a.unicode // false	
b.unicode // true

4.4 y修飾符

y修飾符與 g修飾符類似,也是全局匹配,後一次匹配都是從上一次匹配成功的下一個位置開始。區別在於, g修飾符只要剩餘位置中存在匹配即可,而 y修飾符是必須從剩餘第一個開始。

var s = 'aaa_aa_a';	
var r1 = /a+/g;	
var r2 = /a+/y;	
r1.exec(s) // ["aaa"]	
r2.exec(s) // ["aaa"]	
r1.exec(s) // ["aa"]  剩餘 '_aa_a'	
r2.exec(s) // null

lastIndex屬性: 指定匹配的開始位置:

const a = /a/y;	
a.lastIndex = 2;  // 從2號位置開始匹配	
a.exec('wahaha'); // null	
a.lastIndex = 3;  // 從3號位置開始匹配	
let c = a.exec('wahaha');	
c.index;          // 3	
a.lastIndex;      // 4

返回多個匹配y修飾符對 match方法只能返回第一個匹配,與 g修飾符搭配能返回所有匹配。

'a1a2a3'.match(/a\d/y);  // ["a1"]	
'a1a2a3'.match(/a\d/gy); // ["a1", "a2", "a3"]

檢查是否使用 y修飾符sticky屬性檢查。

const a = /hello\d/y;	
a.sticky;     // true

4.5 flags屬性

flags屬性返回所有正則表達式的修飾符。

/abc/ig.flags;  // 'gi'

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