var和变量提升
js
代码是有两个步骤,先解释,后执行。在解释的过程中会将var
声明的变量提升至当前作用域的最顶端,然后再一步步执行。
var elem = 'test';
if(elem){
console.log(elem); //test
}else{
var str = 'hello world';
}
console.log(str); //undefined
上例的代码js
在解释的过程中会转换成以下代码,也就是明明没有执行声明str
的代码,但是str
却默认有了undefined
这个值,这个就显得有点不合常理,所以为了解决这个问题,在ES6
中引入了const
和let
。
var str = undefined;
var elem = 'test';
if(elem){
console.log(elem); //test
}else{
str = 'hello world';
}
console.log(str); //undefined
var和const 和 let区别
区别一:let 和 const只在块级作用域里面可见
块级作用域是ES6
引入的,var
只受函数作用域和全局作用域影响。如果将上例代码中的var
改成let
。
let elem = 'test';
if(elem){
console.log(elem); //test
}else{
let str = 'hello world';
}
console.log(str); // Uncaught ReferenceError: str is not defined
看一道面试题
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6]();
上面代码中,变量i
是var
命令声明的,在全局范围内都有效,所以全局只有一个变量i
。每一次循环,变量i
的值都会发生改变,而循环内被赋给数组a
的函数内部的console.log(i)
,里面的i指向的就是全局的i
。也就是说,所有数组a
的成员里面的i
,指向的都是同一个i
,导致运行时输出的是最后一轮的i的值,也就是 10。
如果使用let
,声明的变量仅在块级作用域内有效,最后输出的是 6。
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6]();
上面代码中,变量i是let声明的,当前的i
只在本轮循环有效,所以每一次循环的i
其实都是一个新的变量,所以最后输出的是6。你可能会问,如果每一轮循环的变量i都是重新声明的,那它怎么知道上一轮循环的值,从而计算出本轮循环的值?这是因为 JavaScript
引擎内部会记住上一轮循环的值,初始化本轮的变量i
时,就在上一轮循环的基础上进行计算。
区别二:let和const存在暂时性死区
在代码块内,使用let
、const
命令声明变量之前,该变量都是不可用的。这在语法上,称为暂时性死区(temporal dead zone,简称 TDZ)。
console.log(elem); //undefined
var elem = 'hello world';
console.log(elem); //ReferenceError: Cannot access 'elem' before initialization
let elem = 'hello world';
const和let区别
let
和const
都是ES6
新增的语法,这里提一下两者的相同点:
- 只在声明所在的块级作用域内有效。
- 不允许在相同作用域内,重复声明同一个变量。
区别:声明的变量类型不同
const
声明的是常量不能修改,let
声明的是变量可以修改。不过得注意的是const
声明的常量的数据类型。如果是基本类型不可修改,如果是引用类型,可以修改键值,但是不能修改地址。const修改引用类型
let elem = 'hello';
elem = 'world';
console.log(elem); // world
const elem = 'hello';
elem = 'world';
console.log(elem); // TypeError: Assignment to constant variable.
const
声明的变量不得改变值,这意味着,const
一旦声明变量,就必须立即初始化,不能留到以后赋值。
let elem;
elem = 'hello';
console.log(elem); //'hello'
const elem;
elem = 'hello';
console.log(elem); //SyntaxError: Missing initializer in const declaration