一、沒有宣告提升
var有宣告提升,
用let來宣告變數時,不會將宣告提升到最頂部,
console.log(val); // 0
var val = 0;
console.log(a); // Cannot access 'a' before initialization
let a = 1;
因此,當我們使用let來宣告變數時,一定要先宣告再使用,
注意: let宣告的變數不會被掛載到window物件上,
let a = 1;
console.log(a); // 1
console.log(window.a); // undefined
二、塊級作用域
var不存在塊級作用域,只有全域作用域和函式作用域,
ES6中存在塊級作用域,let僅在代碼塊內有效,(用大括號括起來的區域就是代碼塊,引擎會自動識別它,)
{
var val = 0;
let a = 1;
console.log(a); // 1 (在內部可以被訪問到)
}
console.log(val); // 0
console.log(a); // ReferenceError: a is not defined (到了外部就不存在了)
這和立即執行函式有異曲同工之妙,達到了保護私有變數,防止污染全域的作用,
(function() {
var a = 1;
console.log(a); // 1
})();
console.log(a); // ReferenceError: a is not defined
三、暫時性死區(temporal dead zone)
在使用let的代碼塊中的變數會系結在當前的塊級作用域中,不受外部作用域干擾,
let a = 0;
{
console.log(a);
let a = 10;
}

在變數用let宣告之前都是不可以用的,(let沒有宣告提升)
這種語法就叫做暫時性死區,
簡而言之,塊級作用域內用let宣告的變數不可以在宣告之前使用,
四、不允許重復宣告變數
var可以宣告多次,
在同一作用域中,let只能宣告一次,
let a = 1;
let a = 5;
console.log(a); // SyntaxError: Identifier 'a' has already been declared
五、for回圈計數器
一個問題
for(var i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}

運行一下結果是10個10,為什么呢?
第一,var宣告的i可以在全域訪問到,因此可能會出現覆寫現象,
第二,for回圈內的計數器是異步執行的,
綜合以上兩點,1秒后執行10個setTimeout函式,因為i是定義在全域作用域上的,因此,變數i早就被覆寫成了10,
于是列印出10個10,
解決方案一:立即執行函式
解決問題之前,我們分析到問題的關鍵是i作為全域變數被污染(覆寫),這才導致了結果出現誤差,
那么解決這種問題,我們首先想到的就是立即執行函式(IIFE),
立即執行函式也叫自執行函式,它的作用就是封裝私有變數,防止全域變數受污染,
for(var i = 0; i < 10; i++) {
(function(j){
setTimeout(function() {
console.log(j);
}, 1000);
})(i);
}

解決方案二:let
因為let只在代碼塊內有效,因此使用let就避免了變數污染的問題,
for(let i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/100538.html
標籤:JavaScript
上一篇:JS 同步轉異步之Promise
下一篇:ES6中的const
