var关键字:
var声明的范围是函数作用域;即:var在函数内部声明一个变量,那么这个变量是该函数的局部变量,只有在函数内部才能访问,函数外部无法访问(当然如果用闭包可以实现从外部访问,关于闭包:JS中的闭包 ) var 关键字在全局全局作用域中声明的变量会成为window对象的属性 如果在非严格模式下的函数中,未用var声明就给一个变量赋值,那么该变量会变成全局变量,即在函数外部也可访问;而在严格模式下这样给未声明的变量赋值会报错ReferenceError(未定义/引用错误)
function test ( ) {
num = 100 ;
}
test ( ) ;
用var声明的变量会自动提升到函数作用域的顶部,需要注意的是,声明提升只是提升变量声明,并不会提升变量赋值,所以下边的代码输出是undefined,而不是2020:
function test ( ) {
console. log ( year) ;
var year = 2020 ;
}
test ( ) ;
function test ( ) {
var year;
console. log ( year) ;
year = 2020 ;
}
let关键字:
let关键字的作用范围是块级作用域;块简单的理解就是用{ }包起来的一个范围,所以块级作用域是函数作用域的子集;在下边的代码中,num的块级作用域是if{ },所以在if{ }外部打印这个变量会报错
function test ( ) {
if ( true ) {
let num = 100 ;
console. log ( num) ;
}
console. log ( num) ;
}
test ( ) ;
var num = 10 ;
var num = 100 ;
console. log ( num) ;
let year = 2018 ;
let year = 2020 ;
console. log ( year) ;
对变量的冗余声明不会因为混用 let 和 var 而受影响,即如果分别用 let 和 var 对同一个变量进行声明,那么也是会报错;
let num = 100 ;
var num = 10 ;
var year = 2018 ;
let year = 2020 ;
let 关键字没有声明提升;在JS引擎解析代码时,会注意在块后边出现的 let 声明,但在此之前不能以任何方式来引用未声明的变量,否则会报错(ReferenceError)。在 let 声明之前执行的瞬间被称为“暂时性死区”。
console. log ( num) ;
let num = 100 ;
let 关键字在全局作用域中声明的变量不会成为window对象的属性;但 let 声明依然是在全局作用域中发生的,相应变量会在页面生命周期内存续(因此要确保页面不会重复声明同一变量)
const关键字:
const声明变量时必须同时初始化变量,即给变量赋初值 用const声明的变量是不能修改的,如果修改则会报错(TypeError)
const age = 18 ;
age = 20 ;
但如果const指向的是一个对象,那么给这个对象里边的属性赋值是可以的
const per = {
name: 'zhang' ,
age: 18
}
per. age = 20 ;
console. log ( per. age) ;
per. num = 100 ;
console. log ( per. num) ;
const 其他行为和 let 基本相同:const 也不允许重复声明同一变量;作用域也是块级作用域
for 循环中的 var、let、const
for ( var i = 0 ; i < 5 ; ++ i) {
setTimeout ( ( ) => console. log ( i) , 0 )
}
for ( let i = 0 ; i < 5 ; i++ ) {
setTimeout ( ( ) => console. log ( i) , 0 )
}
for ( const i = 0 ; i < 5 ; i++ ) {
setTimeout ( function ( ) {
console. log ( i) ;
} , 0 ) ;
}
let i = 0 ;
for ( const j = 7 ; i < 5 ; ++ i) {
console. log ( j) ;
}
for ( const key in { a: 1 , b: 2 } ) {
console. log ( key) ;
}
for ( const value of [ 1 , 2 , 3 , 4 , 5 ] ) {
console. log ( value) ;
}