阮一峰大神ECMAScript 6 入門|筆記整理
阿新 • • 發佈:2020-08-03
阮一峰大神ECMAScript 6 入門:https://es6.ruanyifeng.com/
let 和 const 命令
- let宣告的變數只在它所在的程式碼塊有效。
- 變數
i
是var
命令宣告的,在全域性範圍內都有效,所以全域性只有一個變數i
。 - 變數
i
是let
宣告的,當前的i
只在本輪迴圈有效,所以每一次迴圈的i
其實都是一個新的變數
- 另外,
for
迴圈還有一個特別之處,就是設定迴圈變數的那部分是一個父作用域,而迴圈體內部是一個單獨的子作用域。
for (let i = 0; i < 3; i++) { let i = 'abc'; console.log(i); }// abc // abc // abc
- ES6 明確規定,如果區塊中存在
let
和const
命令,這個區塊對這些命令宣告的變數,從一開始就形成了封閉作用域。凡是在宣告之前就使用這些變數,就會報錯。即不存在變數提升。
- 暫時性死區的本質就是,只要一進入當前作用域,所要使用的變數就已經存在了,但是不可獲取,只有等到宣告變數的那一行程式碼出現,才可以獲取和使用該變數。
let
不允許在相同作用域內,重複宣告同一個變數。
function func(arg) { let arg; //不能在函式內部重新宣告引數。 } func() // 報錯 function func(arg) { { let arg; } } func()// 不報錯
- 允許在塊級作用域內宣告函式。
- 函式宣告類似於
var
,即會提升到全域性作用域或函式作用域的頭部。 - 同時,函式宣告還會提升到所在的塊級作用域的頭部。
// 塊級作用域內部的函式宣告語句,建議不要使用
{ let a = 'secret'; function f() { return a; } }
// 塊級作用域內部,優先使用函式表示式
{ let a = 'secret'; let f = function () { return a; }; }
const
一旦宣告變數,就必須立即初始化,不能留到以後賦值。
const
- ES6 一共有 6 種宣告變數的方法。
var
命令和function
命令。let
和const
命令,import
命令和class
命令。
- ES6 一方面規定,為了保持相容性,
var
命令和function
命令宣告的全域性變數,依舊是頂層物件的屬性;另一方面規定,let
命令、const
命令、class
命令宣告的全域性變數,不屬於頂層物件的屬性。也就是說,從 ES6 開始,全域性變數將逐步與頂層物件的屬性脫鉤。
- 全域性環境中,
this
會返回頂層物件。但是,Node 模組和 ES6 模組中,this
返回的是當前模組。 - 函式裡面的
this
,如果函式不是作為物件的方法執行,而是單純作為函式執行,this
會指向頂層物件。但是,嚴格模式下,這時this
會返回undefined
。
變數的解構賦值
- ES6 允許按照一定模式,從陣列和物件中提取值,對變數進行賦值,這被稱為解構。
- 如果解構不成功,變數的值就等於
undefined
。
- 陣列的元素是按次序排列的,變數的取值由它的位置決定;
- 而物件的屬性沒有次序,變數必須與屬性同名,才能取到正確的值。
let { foo: baz } = { foo: 'aaa', bar: 'bbb' }; baz // "aaa" let { foo: baz } = { foo: 'aaa', bar: 'bbb' }; baz // "aaa" foo // error: foo is not defined //上面程式碼中,foo是匹配的模式,baz才是變數。真正被賦值的是變數baz,而不是模式foo。 const node = { loc: { start: { line: 1, column: 5 } } }; let { loc, loc: { start }, loc: { start: { line }} } = node; line // 1 loc // Object {start: Object} start // Object {line: 1, column: 5} // 報錯 let {foo: {bar}} = {baz: 'baz'}; //whywhywhy???
- 物件的解構也可以指定預設值。
var {x = 3} = {}; x // 3 var {x, y = 5} = {x: 1}; x // 1 y // 5 var {x: y = 3} = {}; y // 3 var {x: y = 3} = {x: 5}; y // 5 var { message: msg = 'Something went wrong' } = {}; msg // "Something went wrong" // 錯誤的寫法 let x; {x} = {x: 1}; // SyntaxError: syntax error // 正確的寫法 let x; ({x} = {x: 1}); //只有不將大括號寫在行首,避免 JavaScript 將其解釋為程式碼塊,才能解決這個問題。
- 字串也可以解構賦值。
const [a, b, c, d, e] = 'hello'; a // "h" b // "e" c // "l" d // "l" e // "o"
- 解構賦值的規則是,只要等號右邊的值不是物件或陣列,就先將其轉為物件。由於
undefined
和null
無法轉為物件,所以對它們進行解構賦值,都會報錯。
- 函式也可以解構賦值。
[[1, 2], [3, 4]].map(([a, b]) => a + b); // [ 3, 7 ]
- 不得使用圓括號的情況
- 變數宣告語句
- 函式引數
- 賦值語句的模式
//以下三種模式全部報錯 let [(a)] = [1]; let {x: (c)} = {}; function f([(z)]) { return z; } ({ p: a }) = { p: 42 }; ([a]) = [5];
- 只有賦值語句的非模式部分,可以使用圓括號。
[(b)] = [3]; // 正確 ({ p: (d) } = {}); // 正確 [(parseInt.prop)] = [3]; // 正確
- 變數的解構賦值用途
- 交換變數的值
- 從函式返回多個值
- 函式如果要返回多個值,只能將它們放在陣列或物件裡返回。
- 函式引數的定義
- 方便地將一組引數與變數名對應起來。
- 提取 JSON 資料
- 函式引數的預設值review
- 遍歷 Map 結構
- 任何部署了 Iterator 介面的物件,都可以用
for...of
迴圈遍歷。 - Map 結構原生支援 Iterator 介面,配合變數的解構賦值,獲取鍵名和鍵值就非常方便。
- 輸入模組的指定方法 review
//交換變數 let x = 1; let y = 2; [x, y] = [y, x]; // 返回一個物件 function example() { return { foo: 1, bar: 2 }; } let { foo, bar } = example(); //提取 JSON 物件中的資料 let jsonData = { id: 42, status: "OK", data: [867, 5309] }; let { id, status, data: number } = jsonData; //遍歷 Map 結構 const map = new Map(); map.set('first', 'hello'); map.set('second', 'world'); for (let [key, value] of map) { console.log(key + " is " + value); } // first is hello // second is world // 獲取鍵名 for (let [key] of map) { // ... } // 獲取鍵值 for (let [,value] of map) { // ... }
字串的拓展
模板字串
- 用反引號(`)標識。它可以當作普通字串使用,也可以用來定義多行字串,或者在字串中嵌入變數。
- 如果在模板字串中需要使用反引號,則前面要用反斜槓轉義。
- 所有模板字串的空格和換行,都是被保留的,可以使用
trim
方法消除它。 - 模板字串中嵌入變數,需要將變數名寫在
${}
之中。 - 模板字串之中還能呼叫函式。
- 如果模板字串中的變數沒有宣告,將報錯。
$('#result').append(` There are <b>${basket.count}</b> items in your basket, <em>${basket.onSale}</em> are on sale! `); let greeting = `\`Yo\` World!`; $('#list').html(` <ul> <li>first</li> <li>second</li> </ul> `.trim()); function fn() { return "Hello World"; } `foo ${fn()} bar` // foo Hello World bar
例項:模板編譯看不懂
標籤模板 看不懂
字串的新增方法
String.raw()
- 該方法返回一個斜槓都被轉義(即斜槓前面再加一個斜槓)的字串
- 如果原字串的斜槓已經轉義,那麼
String.raw()
會進行再次轉義。
String.raw`Hi\n${2+3}!` // 實際返回 "Hi\\n5!",顯示的是轉義後的結果 "Hi\n5!" //why why why? // `foo${1 + 2}bar` // 等同於 String.raw({ raw: ['foo', 'bar'] }, 1 + 2) // "foo3bar"
確定一個字串是否包含在另一個字串中
- includes():返回布林值,表示是否找到了引數字串。
- startsWith():返回布林值,表示引數字串是否在原字串的頭部。
- endsWith():返回布林值,表示引數字串是否在原字串的尾部。
repeat()
返回一個新字串,表示將原字串重複n
次
引數如果是小數,會被取整。
引數是負數或者Infinity
,會報錯。
引數是 0 到-1 之間的小數,則等同於 0,這是因為會先進行取整運算。
引數NaN
等同於 0。
引數是字串,則會先轉換成數字。
'x'.repeat(3) // "xxx" 'hello'.repeat(2) // "hellohello" 'na'.repeat(2.9) // "nana" 'na'.repeat(-0.9) // "" 'na'.repeat(NaN) // "" //why why why? 'na'.repeat('na') // "" 'na'.repeat('3') // "nanana"
padStart(),padEnd()
- 如果某個字串不夠指定長度,會在頭部或尾部補全。
padStart()
用於頭部補全,padEnd()
用於尾部補全。 - 如果原字串的長度,等於或大於最大長度,則字串補全不生效,返回原字串。
- 如果省略第二個引數,預設使用空格補全長度。
'x'.padStart(4, 'ab') // 'abax' 'x'.padEnd(5, 'ab') // 'xabab' 'xxx'.padStart(2, 'ab') // 'xxx' 'x'.padStart(4) // ' x' 'x'.padEnd(4) // 'x '
trimStart(),trimEnd()
trimStart()
消除字串頭部的空格,trimEnd()
消除尾部的空格。- 它們返回的都是新字串,不會修改原始字串。
const s = ' abc '; s.trim() // "abc" s.trimStart() // "abc " s.trimEnd() // " abc"
matchAll()
- 返回一個正則表示式在當前字串的所有匹配