前端面試題(二):ES6中let,const和 var 三者的區別
let命令基本用法
在ES6中,新增了let命令,用於宣告變數,用來取代ES5中var命令,消除var宣告的變數的不合理,不嚴謹之處。const用於宣告常量。
讓我們來看看let和var的區別
1.let不存在變數提升
使用let宣告的變數,不會像使用var那樣存在“變數提升“”的現象。所以使用let宣告變數,必須遵循“先宣告,後使用”的原則。否則會報錯
console.log(a); //ReferenceError
let a = 10;
如果是var宣告的變數,則不會報錯。
console.log(b); //undefined
var b = 10;
2.let宣告的變數,存在塊級作用域
let宣告的變數只在所宣告的程式碼塊內有效。塊級作用域由 { } 包括,if語句和for語句裡面的{ }也屬於塊作用域。
{
var a = 10;
let b = 20;
}
console.log(a); //10
console.log(b); // ReferenceError: b is not defined
var a =[];
for( var i=0; i<10; i++ ){
a[i] = function(){
console.log(i);
}
}
for( var j = 0; j<a. length; j++ ){
a[j](); //輸出10個10。 因為i是var宣告的,在全域性範圍內都用,每次新的i都會覆蓋原來的。
}
var a =[];
for( let i=0; i<10; i++ ){
a[i] = function(){
console.log(i);
}
}
for( let j = 0; j<a.length; j++ ){
a[j](); //輸出 0,1,2,...,9
}
3.let不允許在同一作用域內重複宣告同一個變數
在同一作用域內,如果使用var宣告同一個變數,則後面的覆蓋前面的
var a = 10;
let a = 10;
console.log(a);//Uncaught SyntaxError:
Identifier 'a' has already been declared
或
let a = 10;
let a = 15;
console.log(a);//Uncaught SyntaxError:
Identifier 'a' has already been declared
4.暫時性死區:在程式碼塊內,使用let宣告變數之前,該變數都是不可以使用用
只要在同一作用域記憶體在let命令,他所宣告的變數就“繫結”在這個作用域內,不管外部有沒有宣告
例如
let a =10;
function fn1(){
console.log(a);
let a = 5;
}
fn1();//Uncaught ReferenceError: a is not defined
ES6規定,如果在區塊中存在let和const宣告的變數,則這個區塊對這些宣告的變數從一開始就形成一個封閉的作用域。不管在外部有沒有宣告這個變數。必須遵守“先宣告,後使用”的原則,否則報錯
ES6規定暫時性死區和不存在變數提升,主要是為了減少執行程式的錯誤,防止出現“先使用(變數),後宣告(變數)”的情況,從而導致意料之外的行為。這種錯誤在ES5中很常見,現在有了這種規定,就可以避免出現此類錯誤了
總之,暫時性死區的本質就是,只要一進入當前作用域,所使用的變數就已存在,但是不可獲取,只有等到宣告變數的哪一行程式碼的出現,在可以獲取和使用該變數
const命令的基本使用
const用來宣告常量,一旦宣告,其值就不能更改
const a = 10;
a = 20;
console.log(a);//Uncaught TypeError:
Assignment to constant variable.
1.const宣告的常量不能改變,意味著const一旦宣告常量,就必須同時初始化。不能先宣告,後初始化,這樣會報錯
2.與let一樣。const宣告的常量也只在塊級作用域內有效
3.與let一樣,必須先宣告,後使用
4.與let一樣,在同一作用域,const不能重複宣告同一常量
那麼如果使用const宣告物件呢?
const b = {
name:'zs',
age:22
}
b.name = "lzx";
console.log(b.name+"---"+b.age);//輸出lzx---22
我們可以看到,使用const宣告的物件的屬性是可以修改。
因為Object型別是引用型別。用const宣告常量儲存的是物件的地址,不可變的是地址,在上面的程式碼中就是,不能把 b 指向另一個物件。而修改物件的屬性,並不會改變物件的地址,因此用const宣告物件的屬性是可以修改的
陣列也是引用型別,同理,不再贅述
參考《ES6 標準入門》(第2版) 阮一峰著