es6筆記

hy_發表於2020-02-05

根據阮一峰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];
複製程式碼

字串

未完待續

相關文章