javascript进阶学习:var、let、const变量声明区别,变量提升,临时死区
在ES6之前我们都是通过var声明变量,而通过var声明变量存在变量提升的问题
在函数作用域或全局作用域中通过var关键字声明的变量,无论实际上是在哪里声明的,都会被当做在当前作用域顶部声明的变量,这就是变量提升机制。
看看下面的例子,分别打印出什么
function test() { console.log(value) } test() //undefined var value="123" test() //123
在声明变量value之前,就调用了函数test,并没有报错(value未定义),而是打印出了undefined。在预编译阶段,javascript引擎将上面的代码修改成下面这样
var value function test() { console.log(value) } test() value="123" test()
再看一个例子
function test(condition) { if(condition){ var value="123" console.log(value) }else { console.log(value) } } test(false) //undefined
condition为false,进入了test函数的else分支,此时并没有定义value,但是打印出来仍然是undefined,而不是报错,在预编译阶段,javascript引擎将上面的代码修改成下面这样,这样看起来就很好理解了
function test(condition) { var value if(condition){ value="123" console.log(value) }else { console.log(value) } } test(false)
再看一个例子
function test() { console.log(value) //undefined var value="456" console.log(value) //456 } var value="123" test()
按理说第一次打印的应该是全局变量value,即“123”,第二次打印的是局部变量value,即“456”,而实际第一次打印的是undefined,这也是由于变量提升导致的,在预编译阶段,javascript引擎将上面的代码修改成下面这样,这样就很容易理解了
function test() { var value console.log(value) value="456" console.log(value) } var value="123" test()
再来看一个经典例子,在循环条件中声明的变量i,在循环体外面,仍然可以访问
for(var i=0;i<10;i++){} console.log(i) //10
let声明的变量不会被提升,let声明的变量在其所在作用域外无法访问
for(let i=0;i<10;i++){} console.log(i) //报错 i is not defined
块级声明用于声明在指定块的作用域之外无法访问的变量,块级作用域(词法作用域)存在于:
函数内部
块中(级{}之间的区域)
如下,通过let声明的value,只在当前块中有效,其他地方使用均报错
function test(condition) { if(condition){ let value="123" }else { console.log(value) // value is not defined } console.log(value) // value is not defined } test(true) test(false)
如果作用域中已经存在某个变量,let禁止重复声明
var value="123" var value="456" //允许 let value="456" //报错 Identifier 'value' has already been declared
const用于声明常量,其值一旦声明不能更改
const value=123 value=456 //报错 Assignment to constant variable.
而如果const声明的是一个对象,则可以更改对象的属性,但是不能更改对象的引用。可以理解为常量存储的是对象的引用地址,只要引用地址不变即可,内容随便变
const obj={ } obj.a=123 //允许 obj={} //报错
const和let一样,不存在变量提升问题
与var不同,let和const声明的变量不会被提升到作用域顶部,如果在声明之前访问这些变量,即使是相对安全的typeof操作,也会触发错误
if(true){ console.log(typeof value) //报错 let value=123 }
在块内部,如在let声明前就使用某个变量,会引发错误,就好像这部分是一个死区一样
点赞(0)