let與const
let聲明的變量只在它所在的代碼塊有效
var命令會發生“變量提升”現象,即變量可以在聲明之前使用,值爲undefined,而let不存在變量提升
ES6 明確規定,如果區塊中存在let和const命令,這個區塊對這些命令聲明的變量,從一開始就形成了封閉作用域。凡是在聲明之前就使用這些變量,就會報錯。總之,在代碼塊內,使用let命令聲明變量之前,該變量都是不可用的。這在語法上,稱爲“暫時性死區”(temporal dead zone,簡稱 TDZ)
ES6 規定暫時性死區和let、const語句不出現變量提升,主要是爲了減少運行時錯誤,防止在變量聲明前就使用這個變量,從而導致意料之外的行爲
let不允許在相同作用域內,重複聲明同一個變量
const聲明一個只讀的常量。一旦聲明,常量的值就不能改變,const一旦聲明變量,就必須立即初始化,不能留到以後賦值
對於const來說,只聲明不賦值,就會報錯
const命令聲明的常量也是不提升,同樣存在暫時性死區,只能在聲明的位置後面使用
const的作用域與let命令相同:只在聲明所在的塊級作用域內有效
const實際上保證的,並不是變量的值不得改動,而是變量指向的那個內存地址所保存的數據不得改動。對於簡單類型的數據(數值、字符串、布爾值),值就保存在變量指向的那個內存地址,因此等同於常量。但對於複合類型的數據(主要是對象和數組),變量指向的內存地址,保存的只是一個指向實際數據的指針,const只能保證這個指針是固定的(即總是指向另一個固定的地址),至於它指向的數據結構是不是可變的,就完全不能控制了。因此,將一個對象聲明爲常量必須非常小心
es6聲明變量的六種方法
var,function,let,const,import,class
變量的解構賦值
ES6 允許按照一定模式,從數組和對象中提取值,對變量進行賦值,這被稱爲解構
數組的解構賦值
數組解構賦值分爲完全解構和不完全解構,如果解構不成功,變量的值就等於undefined,如果使用的是剩餘運算符的話,就爲空數組
完全結構:只要等號兩邊的模式相同,左邊的變量就會被賦予對應的值(基本,嵌套,可忽略,剩餘運算符)
不完全解構:等號左邊的模式,只匹配一部分的等號右邊的數組
解構賦值允許指定默認值,ES6 內部使用嚴格相等運算符(===),判斷一個位置是否有值。所以,只有當一個數組成員嚴格等於undefined,默認值纔會生效
對象的解構賦值
對象的解構與數組有一個重要的不同。數組的元素是按次序排列的,變量的取值由它的位置決定;而對象的屬性沒有次序,變量必須與屬性同名,才能取到正確的值
字符串的擴展
- JSON.stringify()
- 模板字符串
- 新增的方法
- includes():返回布爾值,表示是否找到了參數字符串
- startsWith():返回布爾值,表示參數字符串是否在原字符串的頭部
- endsWith():返回布爾值,表示參數字符串是否在原字符串的尾部
- repeat方法返回一個新字符串,表示將原字符串重複n次
- 如果某個字符串不夠指定長度,會在頭部或尾部補全。padStart()用於頭部補全,padEnd()用於尾部補全
- matchAll()方法返回一個正則表達式在當前字符串的所有匹配
- 字符串對象共有 4 個方法,可以使用正則表達式:match()、replace()、search()和split()
數值的擴展
- Number.isFinite()用來檢查一個數值是否爲有限的(finite),即不是Infinity,注意,如果參數類型不是數值,Number.isFinite一律返回false
- Number.isNaN()用來檢查一個值是否爲NaN,非NaN一律返回false
- Number.parseInt(), Number.parseFloat()
- Number.isInteger()用來判斷一個數值是否爲整,如果參數不是數值,Number.isInteger返回false
- Number()將非數值的值轉爲數值
- Math.trunc方法用於去除一個數的小數部分,返回整數部分,對於非數值,Math.trunc內部使用Number方法將其先轉爲數值,對於空值和無法截取整數的值,返回NaN
函數的擴展
- 函數默認值
- 參數默認值可以與解構賦值的默認值,結合起來使用
- 通常情況下,定義了默認值的參數,應該是函數的尾參數
- 剩餘參數
...rest
,其實rest
是一個參數數組 - 箭頭函數
- 如果箭頭函數不需要參數或需要多個參數,就使用一個圓括號代表參數部分
- 如果箭頭函數的代碼塊部分多於一條語句,就要使用大括號將它們括起來,並且使用return語句返回
- 由於大括號被解釋爲代碼塊,所以如果箭頭函數直接返回一個對象,必須在對象外面加上括號,否則會報錯
- 箭頭函數可以與變量解構結合使用
const full = ({ first, last }) => first + ' ' + last; // 等同於 function full(person) { return person.first + ' ' + person.last; }
數組的擴展
- 擴展運算符是三個點
...
- 擴展運算符的應用
- 複製數組,擴展運算符提供了複製數組的簡便寫法
- 合併數組,擴展運算符提供了數組合並的新寫法
- 擴展運算符可以與解構賦值結合起來,用於生成數組
- 只有函數調用時,擴展運算符纔可以放在圓括號中,否則會報錯
- Array.from方法用於將兩類對象轉爲真正的數組:類似數組的對象和可遍歷的對象
- Array.of方法用於將一組值,轉換爲數組,如果沒有參數,就返回一個空數組
Promise
Promise對象是一個構造函數,用來生成Promise實例
const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 異步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
- Promise構造函數接受一個函數作爲參數,該函數的兩個參數分別是resolve和reject
- Promise實例生成以後,可以用then方法分別指定resolved狀態和rejected狀態的回調函數
- then方法可以接受兩個回調函數作爲參數。第一個回調函數是Promise對象的狀態變爲resolved時調用,第二個回調函數是Promise對象的狀態變爲rejected時調用。其中,第二個函數是可選的,不一定要提供。這兩個函數都接受Promise對象傳出的值作爲參數
- Promise 新建後就會立即執行
- catch用於指定發生錯誤時的回調函數
async與await
- async函數返回一個 Promise 對象,可以使用then方法添加回調函數
- async函數內部return語句返回的值,會成爲then方法回調函數的參數
- 正常情況下,await命令後面是一個 Promise 對象,返回該對象的結果。如果不是 Promise 對象,就直接返回對應的值
- await命令後面的Promise對象,運行結果可能是rejected,所以最好把await命令放在try…catch代碼塊中
- 多個await命令後面的異步操作,如果不存在繼發關係,最好讓它們同時觸發
- await命令只能用在async函數之中,如果用在普通函數,就會報錯
// 寫法一
let [foo, bar] = await Promise.all([getFoo(), getBar()]);
// 寫法二
let fooPromise = getFoo();
let barPromise = getBar();
let foo = await fooPromise;
let bar = await barPromise;