變量聲明
在JavaScript中聲明變量有三個關鍵字
var是最原始的,那就不必多說了,現在主要說的是let和const這兩個關鍵字來聲明變量和var有何不同
let
應用:在業務邏輯很複雜的時候,可以防止內層變量覆蓋外層變量
eg1.
if (true) {
let a = 3;
console.log(a); //3
}
console.log(a); //a is not defined
可以看到在if語句裏面可以訪問a變量
但是在if語句的外面是訪問不了的.
特點1
用let聲明的變量只在當前作用域中生效
eg2.
if (true) {
let b = 4;
if (true) {
let c = 6;
console.log(b) //4
}
console.log(b); //4
console.log(c); //c is not defined
}
if (true) {
var b = 4;
let a = 2;
}
console.log(b); //4
console.log(a); //a is not defined
這個例子可以看出:在一個大括號中,使用let聲明的變量才具有塊級作用域,var關鍵字是不具有的
使用塊級作用域還有一個好處
可以防止循環變量變成全局變量
eg3.
for (var i = 0; i < 4; i++) {
console.log(i); //0 1 2 3
}
console.log(i); //4
在循環體的外面還是可以訪問到變量i,如果這個for循環存在於全局作用域中,那我的變量 i 就變成了全局作用域;循環結束, i 變量就沒有必要了,
所以可以使用let來聲明變量
eg4.
for (let i = 0; i < 4; i++) {
console.log(i); //0 1 2 3
}
console.log(i); // i is not defined
這樣就可以防止 i 變量變成全局變量了;
特點2
使用let來聲明的變量不存在變量提升
eg5.
console.log(a);
let a = 4; //報錯
特點3
使用let來聲明的變量具有暫時性死區
也就是說 在塊級作用域內使用let關鍵字聲明的變量會被整體綁定在塊級區域,不再受外部影響;
eg6.
var a = 3;
if (true) {
console.log(a); //報錯
let a = 4;
}
不會再向上級作用域查找變量a;
因爲在塊級作用域中用 let 聲明瞭變量 a ,那麼變量 a 就跟這個塊級作用域綁定在一起,不受外界影響.所以在聲明之前直接輸出 a 變量會報錯.因此,在該作用域內使用 let 聲明的變量,跟外面的同名變量是沒有關係.
思考題
1.
var arr = [];
for (var i = 0; i < 4; i++) {
arr[i] = function() {
console.log(i);
}
}
arr[0](); // ?
arr[1](); // ?
答案: 4 4
解析: for循環處於全局作用域中,在裏面用var創建了一個變量 i , 變量 i 就是全局變量,函數執行時,for循環早就已經循環結束,此時 i 的值已經是4了,所以函數輸出的值是4.由於數組中存了兩個函數,在執行時輸出的都是全局變量 i ,所以兩次輸出都是4,關鍵點在於變量 i 是全局的,函數執行時輸出的都是全局作用域下的 i 值
2.
let arr = [];
for (let i = 0; i < 4; i++) {
arr[i] = function() {
console.log(i);
}
}
arr[0](); // ?
arr[1](); // ?
答案: 0 1
解析:由於使用let關鍵字聲明的變量具有塊級作用域.在for循環結束後,產生了兩個塊級作用域,產生的兩個塊級作用域中都用自己的變量 i 互不影響,數組中存儲的兩個函數在執行時,要分別在自己的塊級作用域中查找變量 i ,第一個函數執行時,輸出的是第一個塊級作用域中的 i 值 ,就是0; 第二個函數輸出的第二個塊級作用域中的 i 就是 1; 關鍵點 :每一次循環都產生一個塊級作用域,每個塊級作用域裏面的變量都是不同的.
const
作用: 聲明常量,常量就是值(內存地址) 不能變化的量
特點1:具有塊級作用域
eg7.
if (true) {
const a = 3;
}
console.log(a); //a is not defined
所以在 if 語句裏面用const聲明的常量a,在外面是訪問不到 a 變量的
eg8.
if (true) {
const a = 3;
if (true) {
const a = 5;
console.log(a); //5
}
console.log(a); //3
}
console.log(a); //a is not defined
每個塊級作用域中的同名變量互不影響
特點2: 使用const關鍵字聲明的變量必須賦值,否則會報錯
eg9.
const a //報錯 .Missing intializer in const declaration
意思是,丟失了初始值;
所以用const聲明的常量一定要賦初始值
特點3 使用const聲明的常量,值不能修改
分兩種情況.
1,基本數據類型
一旦賦值,值不可更改,(比如數值或者字符串類型的值)
eg10.
const a =3;
a=5;
報錯// Assignemt to constant variable
2,複雜數據類型
不能重新賦值,但是可以更改數據結構內部的值(比如數組,或者對象)
eg10.
const arr = [1, 3];
arr[0] = 2;
arr[1] = 4;
console.log(arr); // 2 4
因爲只更改了arr數組內部的值,並沒有改變存儲的地址
arr = [5, 6] 報錯 //Assignment to constant variable
這裏arr變成了一個新數組,地址都不一樣的了,所以會報錯
所以說對於賦值數據類型來說,內部的值可以更改,但是重新賦值就是不行.
也就是說常量值對應的內存地址不可更改
總結
let const var 的區別
1. 使用 var 聲明的變量,作用域爲該語句所在的函數內,存在變量提升
2. 使用 let 聲明的變量,作用域爲該語句所在的代碼塊內,不存在變量提升
3. 使用const聲明的是常量, 在後面出現的代碼中不可更改該常量的值.不存在變量提升
var | let | const |
---|---|---|
函數作用域 | 塊級作用域 | 塊級作用域 |
變量提升 | 不存在變量提升 | 不存在變量提升 |
值可以改 | 值可以改 | 值不可以改 |