前言
感謝你能點進這篇文章,首先我先做一個說明,我是今年剛畢業的前端應屆生,這篇文章是我學習ES6的let
和const
部分之後,自己做的歸納筆記,也是我的第一篇文章。第一次做這種文章類的分享,而且是在一個大平臺上,如果有不足,希望可以幫我點出,十分感謝。
其實在發表文章之前,我們公司前端組的大佬就一直鼓勵我去做文章分享,打造自己的一個品牌。但是由於自己性格問題和懶惰,一直在拖。畢竟我最開始並不覺得自己有什麼能分享的,但是後續慢慢的才理解到一個真理:分享是沒有門檻的。所以開始嘗試做這種事情,希望可以慢慢做好,畢竟也是對自己的一種提升和鍛鍊。之後會繼續更新ES6的學習記錄文章,文章的內容,都是通過自己理解之後,然後用自己的話語去進行一個描述,當中可能會有不太準確或者不太恰當的描述,也歡迎觀看文章的您提出這類的意見和建議。同時我的文章會進行一些內容的驗證,有些部分可能會驗證的有點多,也請多擔待。
最後補充一句,我目前ES6系列學習的主要文獻是阮一峰大神的《ECMAScript 6 入門》。
那就正式開始吧。
Let命令
let
命令用於宣告變數,用法類似於var
,但是let
命令有個特點那就是隻會作用在let
所在的作用域內。
Let命令的作用域
let a = 1;
{
var b = 2;
var c = a;
let d = 3;
}
a // 1
b // 2
c // 1
d // ReferenceError: b is not defined
複製程式碼
這裡的a
引數的let
命令用法毫無意義,如果這樣使用就和var
沒區別,倒不如說要這樣使用還不如使用var
。
for
迴圈則非常適合使用該命令
for(let i=0;i<1;i++){
console.log('A',i);
}
console.log('B',i);
// A 0
// ReferenceError: i is not defined
複製程式碼
在for
迴圈中使用let
命令,每一輪迴圈的i
都是一個新的變數,如果在內部使用計算公式等,則會通過JavaScript
引擎記住上一輪迴圈結果的值,然後對其進行後續的迴圈計算,總而完成計算。
for(let i = 0;i<3;i++){
let i = 'a';
console.log(i);
}
// a
// a
// a
複製程式碼
此處是在
for
迴圈中使用let
時候的一個特點,當子作用域中使用let再次定義了一個與父作用域中相同名稱的引數時,兩個引數互不干擾。
暫時性死區
只要塊級作用域記憶體在let
命令,它所宣告的變數就“繫結”這個區域,不再受外部的影響。
let a = 1;
let b = 1;
{
let a = 2;
b = 2;
console.log('a1',a);
console.log('b1',b);
}
console.log('a2',a);
console.log('b2',b);
// a1 2
// b1 2
// a2 1
// b2 2
複製程式碼
當分別在父作用域和子作用域內使用
let
定義引數時,即便引數名相同,他們也不是同一個引數。父作用域中定義的引數,只會作用在自身作用域和未重新使用let
命令定義同名引數的子作用域中。該情況就是自作用於中的let
命令產生了暫時性死區。
var a = 1;
{
console.log(a)
let a = 2;
}
// ReferenceError: a is not defined
複製程式碼
以上程式碼可知,作用域內只要使用了
let
命令宣告的引數,即便有同名全域性變數,也無法在let
命令程式碼執行之前對該引數進行任意操作,即使這個操作和let
命令是屬於同一個作用域
let
的暫時性死區的特點, 會導致任意作用域,只要某個引數有對應的let
宣告,無論該宣告的位置在哪,該作用域內的該引數,便會完全獨立於在該作用域內,不會受到全域性或者父作用域中同名引數的干擾。
不允許重複宣告
注意一點,let
命令是個小貪心鬼,同作用域內不允許有其他同名引數,無論是第二次同名命名是使用var
還是let
,都會報錯。其子作用域中,也必須使用let
命令進行同名命名,否則也會報錯。
let a = 1;
let a = 2;
console.log(a);
// Identifier 'a' has already been declared
複製程式碼
var a = 1;
let a = 2;
console.log(a);
// Identifier 'a' has already been declared
複製程式碼
let a = 1;
var a = 2
console.log(a);
// Identifier 'a' has already been declared
複製程式碼
var a = 1;
var a = 2;
console.log(a);
// 2
複製程式碼
let a = 1;
{
var a = 2;
console.log(a);
}
console.log(a);
複製程式碼
以上程式碼若在
chrome
除錯皮膚測試時,請切記手動改引數名或者清除上一次程式碼所命名的引數。
Let命令不存在變數提升
所謂變數提升,就是變數可以在宣告程式碼之前使用,不會出現報錯,不過值未undefined
,var
便有該特點。
console.log(a);
var a = 1;
// undefined
console.log(b);
let b = 1;
// Identifier 'b' has already been declared
複製程式碼
使用
var
命令宣告的引數,即會發生變數提升的引數,在指令碼開始執行時,對應的變數就已經被建立,直到執行到實際定義引數的程式碼時,該引數才會被賦上對應的值。
塊級作用域與函式宣告
概念
在ES5中,一般只有全域性作用域和函式作用域。
而在ES6中,增加了一個塊級作用域。ES6 規定,塊級作用域之中,函式宣告語句的行為類似於let,在塊級作用域之外不可引用。
一般而言,每個{}
內部就是一個塊級作用域。
function f() { console.log('I am outside!'); }
(function () {
if (false) {
function f() { console.log('I am inside!'); }
}
f();}());
// Uncaught TypeError: f is not a function
複製程式碼
上述程式碼在ES6環境中執行的時候,會出現報錯,因為兩次宣告的function
和執行的f()
不在同一塊級作用域。
注意點
ES6改變了塊級作用域內宣告的函式的處理規則,但是由於網際網路目前的現狀是多個版本環境同時並行的情況。所以ES6有以下規定:
- 允許在塊級作用域內宣告函式
- 函式宣告類似於
var
,即會提升到全域性作用域或函式作用域的頭部。 - 同時,函式宣告還會提升到所在的塊級作用域的頭部。
以上規則只對ES6的瀏覽器生效。在其他環境下不會生效。
綜上所述,我們需要儘量避免在塊級作用域內宣告函式。如果無法避免,也要寫成函式表示式。並且塊級作用域的宣告函式規則,必須在使用{}
的情況下使用,不可以使用簡寫。
if(true)
function f() {}
//報錯
複製程式碼
const命令
概念
const
用於宣告一個只讀的常量。
特點
由於const
宣告的常量為只讀,所以其宣告的常量無法修改。
const a = 123;
a //123
a = 321; // TypeError: Assignment to constant variable.
複製程式碼
宣告的常量不能再次修改,所以意味著他必須在宣告的時候就進行賦值。因為如果不這樣做,你的宣告就沒有意義。
const a; // SyntaxError: Missing initializer in const declaration
複製程式碼
const
和let
相似,只在塊級作用域內生效,同時也不提升和存在暫時性死區。
if(true){
const a = 1;
}
a // ReferenceError: a is not defined
if(true){
console.log(b);
const b = 1;
}
//ReferenceError: b is not defined
複製程式碼
同時也和let
命令一樣,在同一塊級作用域內,不可重複使用一樣的名稱,即便一個是宣告常量,一個是宣告變數。
var a = 1;
let b = 1;
const a = 2; // SyntaxError: Identifier 'a' has already been declared
const b = 2; // SyntaxError: Identifier 'b' has already been declared
複製程式碼
本質
const
並不是變數的值不可改變,而是變數所指向的那個記憶體地址所儲存的資料不得改變。特別是複合型別的資料,變數指向的記憶體地址,儲存的只是一個指向實際資料的指標,const
只能保證指標是固定的。
聽起來其實有點繞,我個人的理解是,比如你需要調某個倉庫的貨物,然後我告訴你倉庫的地址,我只能保障那個倉庫的位置在那裡不變,但是倉庫裡面放什麼我就無法保證了。
const a = {};
a.prop = 1;
a.prop; // 1
複製程式碼
因此,使用const
宣告的時候需要格外小心,不然就是紅紅的報錯了。(雖然快過年了,但是程式碼還是別增添顧念的氣氛了)
一些小補充
頂層物件的屬性
在ES5中,頂層物件的屬性和全域性變數是等價的,也就是說全域性變數的a = 1
等同於 window.a = 1
。
ES6中,為了改變這個情況,給var
和function
命令保留了原有的這個特性的同時。也規定了let
、const
和class
等命令所宣告的全域性變數,不屬於頂層物件的屬性。
var a = 1;
window.a //1
let b = a;
window.b //undefined
複製程式碼
總結
第一篇結束了,一開始寫的時候特別亂,然後慢慢調整成了目前這一篇。如果你覺得還可以,希望可以幫點個贊。之後的更新我會繼續奉上,也希望能受到你的喜歡和收到你的意見和建議,十分感謝。