var存在变量提升,而let没有
console.log(window.name) //undefined
console.log(window.age) // SyntaxError
var name = 'tom'
let age = 12
上面的代码,被js引擎修改为
var name
console.log(window.name) //undefined
console.log(window.age) // SyntaxError
name = 'tom'
let age = 12
var声明的全局变量会成为window的属性而let则不会
使用var声明的全局变量会成为window对象的属性,而let则不会
var name = 'tom'
let age = 12
console.log(window.name) //tom
console.log(window.age) //undefined
但是,上面的age变量仍在全局范围内可以使用
为何var可以重复声明同一个变量,而let不可以?
我们都知道,使用var可以反复声明同一个变量,例如
function foo() {
var name = 'tom'
var name = 'tom'
var name = 'tom'
console.log(name) //tom
}
而使用let则不可以,会报错
function foo() {
let name = 'tom'
let name = 'tom'
let name = 'tom'
console.log(name) //Syntaxerror 因为name已经声明过
}
你可能会说,ES6中规定let不能重复声明,但是为什么呢?
其实这和var与js引擎本身有关
我们都知道,var声明的变量存在着作用域提升
function bar() {
console.log(age)
var age = 12
}
bar() //undefined
之所以不会报错,是因为js引擎执行了以下操作
function bar() {
var age
console.log(age)
age = 12
}
bar() //undefined
这就是所谓的作用域提升(hoist),把所有使用var声明的变量都提升到函数作用域的顶部
可这和var能重复声明有什么关系呢?
这就不得不说js引擎干的另外一件事,它会自动合并作用域顶部的重复声明
function foo() {
...
var name = 'tom'
var name = 'tom'
var name = 'tom'
...
console.log(name) //tom
}
也就是说,像上面这样的重复声明,声明的变量name会被提升到作用有的最顶部
然后js引擎会检测是否存在重复申明的变量,并将多余的声明删除
会被合并成下面这样
function foo() {
var name = 'tom'
...
console.log(name) //tom
}
而由于,let声明的变量作用域就是当前代码块,不能被提升,所以js引擎无法检测到是使用let否声明过同名的变量
从而也就无法合并同名变量
进而导致重复使用let声明重名变量报错
而且,重复声明和使用var与let的方式无关
var name
let name //SyntaxError
let age
var age //SyntaxError