前世
在 const & let 還未出現前,JS 的世界一直是 var的統治
var:在JS中用於變量聲明的關鍵字。
特點:
- 變量提升
- 只有函數作用域或者全局作用域,沒有塊級作用域
- 重複聲明變量
- 循環體重的閉包會出現問題
…….
變量提升
function test(tag) {
console.log(a,b); // a,b在下面聲明,但是會打印出undefined,不會報錯
if(10 >= tag) {
var a = tag + 1;
} else {
var b = tag - 1;
}
}
在瀏覽器預解析機制中,加載函數的時候,此時的作用域爲函數作用域,函數作用域中JS會先將所有的聲明置頂。
function test(tag) {
var a,b; // 將聲明置頂,但是賦值並不會
console.log(a,b); // a,b在下面聲明,但是會打印出undefined,不會報錯
if(10 >= tag) {
var a = tag + 1;
} else {
var b = tag - 1;
}
}
只有函數作用域以及全局作用域,沒有塊級作用域
function test(tag) {
console.log(a,b); // a,b在下面聲明,但是會打印出undefined,不會報錯
if(10 >= tag) {
var a = tag + 1;
} else {
var b = tag - 1;
}
console.log(a); // 9
}
test(8) // 9
按照其他語言規則 if 是一個程序塊,在 if 中聲明的變量作用域只能在 if 中,但是 JS 因爲只有函數作用域和全局作用域,所以纔會導致在 if 判斷外還可以訪問 if 的變量
重複聲明變量
var a = 1;
var a = 2;
console.log(a); // 2
在使用var的時候允許重複聲明變量也是令人頭痛的事情,也許因爲這個機制,可能就會出現bug
循環體重的閉包會出現問題
var arr = [];
for(var i = 0; i < 3; i++) {
arr.push(function () {
return i;
})
}
for(var j = 0; j < 3; j++) {
console.log(arr[j]()); // 3,3,3
}
將var -> let
將會打印出 0,1,2
因爲缺乏塊作用域所以導致問題出現
今生
如今距離ES6規範的出現已經過去了4年多了,在項目中也早已開始大量使用ES6規範編寫代碼了。var也不再是JS世界的唯一了,
JS 世界出現了const & let。
const & let 的出現給JS帶來了塊級作用域,解決了變量提升,禁止了重複聲明變量,讓JS少了很多疑惑的地方。
let & const
相同點:
- 具有塊級作用域
- 禁止重複聲明變量
- 不會產生變量提升
區別:
let
使用let聲明的基本類型變量是可以改變值
let a = 12;
a = 13;
return a; // 13
使用let聲明引用類型的變量是可以改變引用的
let info = {
name: "ming995",
age: 25,
sayHi: function() {
console.log(`Hi I'm ${this.name}`)
}
};
let heInfo = {};
heInfo = info;
heInfo.name = "Jack";
console.log(heInfo);
const
使用const聲明的基本類型變量是不可以改變值
const a = 13;
a = 14;
return a; // 報錯
使用const聲明引用類型的變量是不可以改變引用的
const info = {
name: "ming995",
age: 25,
sayHi: function() {
console.log(`Hi I'm ${this.name}`)
}
};
const heInfo = {};
heInfo = info; // 報錯
heInfo.name = "Jack";
console.log(heInfo);
但是我們可以操作const聲明的引用類型的屬性值
const info = {
name: "ming995",
age: 25,
sayHi: function() {
console.log(`Hi I'm ${this.name}`)
}
};
info.language = "js";
console.log(info);
總結
之前對於const的理解有偏差,所以就寫這篇文章。var時代已經過去了,ES6各種特性用起來。