根據阮一峰es6教程所做的筆記:
- babel是js的轉碼器,可以將es6程式碼轉為es5程式碼
- babel配置檔案,用來設定轉碼規則和外掛
{
"presets": [],
"plugins": []
}
複製程式碼
- babel只轉換js的句法(syntax),不轉換新的api,如es6陣列增加的方法Array.from()就不會轉碼,要是想使用這個方法,必須給使用環境新增墊片
let/const
let宣告的變數只在它所在的程式碼塊中有效(塊級作用域)
for迴圈中設定迴圈變數的作用域(父作用域)跟迴圈體內部每次迴圈的作用域(子作用域)不同
for (let i = 0; i < 5; i++) {
let i = 'a';
console.log(i);
}
複製程式碼
上述中迴圈變數i跟迴圈體中的變數i不同作用域
let宣告的變數不存在變數提升,所以在塊級作用域中,使用某變數時,若該變數未宣告則報ReferenceError,在程式碼塊中宣告變數前的區域就叫暫時性死區(temporal dead zone)
function () {
var i = 10;
if (true) {
i = 100; // ReferenceError
typeof i; // ReferenceError
let i = 1;
}
}
複製程式碼
typeof由於暫時性死區也有可能在執行時丟擲ReferenceError,而一個變數若沒有被宣告,使用typeof返回不會報錯,返回字串undefined
function test (x = y, y = 2) {
return [x, y];
}
複製程式碼
test()時則會丟擲ReferenceError,因為未傳參,y未宣告,屬於死區,test(1)則不會報錯
function test (x = 2, y = x) {
return [x, y];
}
複製程式碼
test()不報錯
在同一個作用域中,不可以使用let重複宣告同一個變數,當然也不同在函式體中重複宣告函式引數
塊級作用域中不建議宣告函式,因為不同的環境可能會導致報錯,如果需要宣告,則使用函式表示式,並且塊級作用域使用大括號
if (true) {
function test () {} // 建議不要使用
}
if (true) {
let test = function () {};
}
複製程式碼
const定義的是隻讀的常量,無法修改,宣告的時候必須初始化,不可以重複宣告,變數不提升,存在暫時性死區,作用域同let一致 const保證的是變數指向的那個記憶體地址所儲存的資料不可修改,簡單型別的資料,值就儲存在那個記憶體地址,所以const宣告就是常量;而複合型別的變數(主要包括物件、陣列),變數指向的記憶體地址上儲存的只是指向實際資料的指標,const保證這個指標是固定的,但指標指向的資料結構可能會發生改變
const obj = {};
obj.name = 'li';
obj = {}; // TypeError
複製程式碼
擴充:要是想將一個物件凍結,則應該使用Object.freeze()
const obj = Object.freeze({});
obj.name = 'li'; // 常規模式下不報錯,嚴格模式下報TypeError
複製程式碼
擴充:將一個物件徹底凍結,包括它的屬性
function constantize (obj) {
Object.freeze(obj);
Object.keys(obj).forEach(key => {
if (typeof obj[key] === 'object') {
constantize(obj[key])
}
})
}
複製程式碼
擴充:es6宣告變數的方法有6種:var、function、let、const、import、class
var在非函式中宣告的變數是全域性物件,但也是頂層物件的屬性,瀏覽器中是window的屬性,node中是global的屬性 let宣告的變數若不在某個程式碼塊中,則是全域性物件,但不是頂層物件的屬性
解構
解構:按照一定模式,從物件或陣列中提取值,對變數進行賦值,這就叫解構(destructuring)
let [a, , c, [[d], e], ...z] = [1, 2, 3, [[4, 5, 6], 7, 8, 9], 10, 11, 12, 13];
複製程式碼
若解構不成功,即沒有在陣列中匹配到該位置上的值,則該變數為undefined,z為[]
let [a, b, ...z] = [1];
複製程式碼
還有種解構叫不完全解構,只匹配右邊陣列中部分的元素
let [a, , b] = [1,2,3,4,5];
複製程式碼
若右邊是不可遍歷的結構(不具備Iterator介面),會報錯
let [ a, b ] = true;
複製程式碼
Set物件可以使用陣列解構
const [ a, b ] = new Set([1,2,3,4]);
複製程式碼
擴充:Generator函式原生具有Iterator介面,可以採用陣列形式結構,這裡略
解構預設值
let [ a, b = 10 ] = [1];
複製程式碼
當b那個位置上的陣列成員嚴格等於undefined時,預設值才會生效,為null都不生效
預設值可以引用解構賦值的其他變數
let [ x, y = x ] = [1,2,3];
複製程式碼
物件解構賦值是按照同名屬性匹配賦值的,解構失敗依然等於undefined
let { a, b } = {a: 1, b: 2};
複製程式碼
物件解構賦值可以方便地將物件的方法取出來
let { log: print } = console; // let { log: log } = console;
複製程式碼
其實物件解構的全寫形式是上述註釋那種,重新命名只需修改後者即可,前者是匹配的模式,而不是變數
物件解構取出來的值若為undefined,則不可以再取子屬性
let { a: { b: myB } } = { name: 'li' }
複製程式碼
物件解構賦值可以取到繼承的屬性
物件解構賦值指定預設值,預設值生效原則依然是取的屬性值嚴格等於undefined
let { a = 10 } = {};
let { a: myA = true } = {};
複製程式碼
將已經宣告的變數進行解構賦值,需加()
let a;
({a} = { a: 10})
複製程式碼
對陣列進行物件屬性的解構
let arr = [1,2,3];
let { 0: first, [arr.length - 1]: last } = arr;
複製程式碼
字串解構賦值,將字串轉換成類似陣列的物件
let [a, b, c] = 'liqi';
let { length: len } = 'liqi';
複製程式碼
對數字和布林型別的變數解構感覺沒啥意思
對null、undefined解構會報錯,因為null、undefined無法轉為物件
函式引數解構
function ([x, y = 10]) {
return [x , y];
}
function test({x = 10, y = 101} = {}) {
return [x, y];
}
test(); // []
test({}); // [10, 101]
test({x: true}); // [true, 101]
function test1({x, y} = {x: 10, y: 10}) {
return [x, y];
}
test1(); // [10, 10]
test1({}); // [undefined, undefined]
test1({x: true}); // [true, undefined]
複製程式碼
交換變數
let x = 10;
let y = 101;
[x, y] = [y, x];
複製程式碼
字串
未完待續