let
和const
是 ES6 新增的命令,用於聲明變量,這兩個命令跟 ES5 的var
有許多不一樣,而且let
和const
也有一些細微的不一樣,在認真閱讀了阮一峯老師的文檔後,發現仍是有一些不知道的細節,從新整理了一下,分享給各位.node
var
和let
/const
的區別es6
塊級做用域數組
不存在變量提高瀏覽器
暫時性死區安全
不可重複聲明bash
let、const聲明的全局變量不會掛在頂層對象下面babel
const
命令兩個注意點:函數
const 聲明以後必須立刻賦值,不然會報錯測試
const 簡單類型一旦聲明就不能再更改,複雜類型(數組、對象等)指針指向的地址不能更改,內部數據能夠更改。ui
ES5只有全局做用域和函數做用域,沒有塊級做用域。
這帶來不少不合理的場景:
var tmp = new Date();
function f() {
console.log(tmp); // 想打印外層的時間做用域
if (false) {
var tmp = 'hello world'; // 這裏聲明的做用域爲整個函數
}
}
f(); // undefined
var s = 'hello';
for (var i = 0; i < s.length; i++) {
console.log(s[i]); // i應該爲這次for循環使用的變量
}
console.log(i); // 5 全局範圍均可以讀到
複製代碼複製代碼
function f1() {
let n = 5;
if (true) {
let n = 10;
console.log(n); // 10 內層的n
}
console.log(n); // 5 當前層的n
}
複製代碼複製代碼
{{{{
{let insane = 'Hello World'}
console.log(insane); // 報錯 讀不到子做用域的變量
}}}};
複製代碼複製代碼
{
let a = ...;
...
}
{
let a = ...;
...
}
複製代碼複製代碼
以上形式,能夠用於測試一些想法,不用擔憂變量重名,也不用擔憂外界干擾
在塊級做用域聲明函數,由於瀏覽器的要兼容老代碼,會產生一些問題!
在塊級做用域聲明函數,最好使用匿名函數的形式。
if(true){
let a = function () {}; // 做用域爲塊級 令聲明的函數做用域範圍更清晰
}
複製代碼複製代碼
ES6 的塊級做用域容許聲明函數的規則,只在使用大括號的狀況下成立,若是沒有使用大括號,就會報錯。
// 報錯
'use strict';
if (true)
function f() {} // 咱們須要給if加個{}
複製代碼複製代碼
變量提高的現象:在同一做用域下,變量能夠在聲明以前使用,值爲 undefined
ES5 時使用var
聲明變量,常常會出現變量提高的現象。
// var 的狀況
console.log(foo); // 輸出undefined
var foo = 2;
// let 的狀況
console.log(bar); // 報錯ReferenceError
let bar = 2;
複製代碼複製代碼
只要一進入當前做用域,所要使用的變量就已經存在了,可是不可獲取,只有等到聲明變量的那一行代碼出現,才能夠獲取和使用該變量
var tmp = 123; // 聲明
if (true) {
tmp = 'abc'; // 報錯 由於本區域有tmp聲明變量
let tmp; // 綁定if這個塊級的做用域 不能出現tmp變量
}
複製代碼複製代碼
暫時性死區和不能變量提高的意義在於:
爲了減小運行時錯誤,防止在變量聲明前就使用這個變量,從而致使意料以外的行爲。
在測試時出現這種狀況:
var a= '聲明';const a = '不報錯'
,這種狀況是由於babel在轉化的時候,作了一些處理,在瀏覽器的控制檯中測試,就成功報錯
let
、const
不容許在相同做用域內,重複聲明同一個變量
function func(arg) {
let arg; // 報錯
}
function func(arg) {
{
let arg; // 不報錯
}
}
複製代碼複製代碼
window
global
var a = 1;
// 若是在 Node環境,能夠寫成 global.a
// 或者採用通用方法,寫成 this.a
window.a // 1
let b = 1;
window.b // undefined
複製代碼複製代碼
一旦聲明,必須立刻賦值
let p; var p1; // 不報錯
const p3 = '立刻賦值'
const p3; // 報錯 沒有賦值
複製代碼複製代碼
const一旦聲明值就不能改變
const p = '不能改變';
p = '報錯'
複製代碼複製代碼
考慮以下狀況:
const p = ['不能改動']
const p2 = {
name: 'OBKoro1'
}
p[0] = '不報錯'
p2.name = '不報錯'
p = ['報錯']
p2 = {
name: '報錯'
}
複製代碼複製代碼
const所說的一旦聲明值就不能改變,實際上指的是:變量指向的那個內存地址所保存的數據不得改動
簡單類型(number、string、boolean):內存地址就是值,即常量(一變就報錯).
複雜類型(對象、數組等):地址保存的是一個指針,const
只能保證指針是固定的(老是指向同一個地址),它內部的值是能夠改變的(不要覺得const就安全了!)
因此只要不從新賦值整個數組/對象, 由於保存的是一個指針,因此對數組使用的push
、shift
、splice
等方法也是容許的,你就是把值一個一個全都刪光了都不會報錯。
複雜類型還有函數,正則等,這點也要注意一下。
再總結一下,看到這些名詞,腦子裏應該會有對應的理解,若是沒有的話,那能夠再看看對應的內容。
let
能夠先聲明稍後再賦值,而const
在 聲明以後必須立刻賦值,不然會報錯
const 簡單類型一旦聲明就不能再更改,複雜類型(數組、對象等)指針指向的地址不能更改,內部數據能夠更改。
let
使用場景:變量,用以替代var
。const
使用場景:常量、聲明匿名函數、箭頭函數的時候。