var聲明提前
var聲明的標識符會在編譯階段被提升到最近的作用域的開頭
塊級聲明
在"if(){}"塊中,var聲明的標識符,在if塊執行完之後還可以訪問,在編譯階段被提升到最近的作用域頭部
console.log(a);
if(true){
console.log(a);
var a=123;
console.log(a)
}
VM145:1 undefined
VM145:3 undefined
VM145:5 123
undefined
console.log(b)
VM172:1 Uncaught ReferenceError: b is not defined
at <anonymous>:1:13
(anonymous) @ VM172:1
let
使用let 可以聲明只能在塊內部能訪問的變量,當代碼塊執行結束,就會自動銷燬,在代碼塊外面不能訪問到這個變量,也不會在編譯階段將這個變量提升到最近的作用域的頭部,在編譯階段會將這個變量放到臨時死區中,在被初始化的時候,從臨時死區取出這個變量,在初始化之前訪問臨時死區中的變量會報錯,即使是 typeof 關鍵字也會報錯
typeof sukla;
if(true){
typeof sukla;
let sukla=123;
console.log(sukla)
}
VM285:3 Uncaught ReferenceError: sukla is not defined
at <anonymous>:3:1
(anonymous) @ VM285:3
typeof sukla
"undefined"
const
使用const定義的變量也和使用let定義的變量一樣具有塊級作用域,不會聲明提前,在初始化之前會被放到臨時死區,初始化之前使用typeof關鍵字報錯
typeof sukla;
if(true){
typeof sukla;
const sukla='123';
console.log(sukla)
}
VM119:3 Uncaught ReferenceError: sukla is not defined
at <anonymous>:3:8
(anonymous) @ VM119:3
typeof sukla
"undefined"
循環中的塊級作用域
let
let在循環中的表現被做了特殊的定義,每次循環開始會銷燬上一輪循環中的同名變量,並用上一次的同名變量的值來初始化一個同名的變量,然後繼續本輪循環,在每一輪循環中的變量都是和其它輪循環中的變量是相對獨立的
var funArr=[];
for(let i=0;i<10;i++){
funArr.push(function(){console.log(i)})
}
funArr.forEach(function(fun){fun()})
VM276:3 0
VM276:3 1
VM276:3 2
VM276:3 3
VM276:3 4
VM276:3 5
VM276:3 6
VM276:3 7
VM276:3 8
VM276:3 9
undefined
const
const在循環中定義的變量也是在每次循環結束時候銷燬,下次循環會使用新值初始化一個新變量,這個過程中,變量的值不能發生改變,所以用自增自減作爲循環改變操作的循環會報錯,用"for in"循環不會報錯,因爲這種循環不會改變循環過程中變量的值
var arr=[1,2,3]
undefined
for(const i=0;i<arr.length;i++){
console.log(i)
}
VM124:2 0
VM124:1 Uncaught TypeError: Assignment to constant variable.
at <anonymous>:1:29
(anonymous) @ VM124:1
var obj={
name:"sukla",
age:26
}
undefined
for(const k in obj){
console.log(obj[k])
}
VM202:2 sukla
VM202:2 26
undefined
全局屬性
var聲明一個全局變量的時候,會在window對象上she'設置一個同名屬性,let、const聲明全局變量時候,不會在window上設置同名屬性
var sukla=123
undefined
window.sukla
123
let sukla1=456
undefined
window.sukla1
undefined
const sukla2=789
undefined
window.sukla2
undefined