一般来说变量的声明有创建,初始化,赋值3个过程。
var变量提升
如下代码:
<script type="text/javascript">
var name='Tom';
(function(){
console.log(name);//输出undefined,为什么?
var name='Tim';
})();
</script>
JavaScript中,变量的声明将被提升到函数的最顶部,所以上面代码其实质应为:
<script type="text/javascript">
var name='Tom';
(function(){
var name;
console.log(name);//输出undefined,很好理解,因为name又被声明了一次,且没有赋值
name='Tim';
})();
</script>
也就是说,var变量的“创建”和 “初始化”都被提升了。
let变量
我们在测试let变量不可重复声明时有如下情况:
<script type="text/javascript">
let name;
console.log(name);
let name="zzs";
</script>
直接报错:Uncaught SyntaxError: Identifier ‘name’ has already been declared,没有输出语句,可见let变量存在变量提升。
我们在测试let变量提升时出现了以下情况
<script type="text/javascript">
console.log(name);
let name="zzs";
</script>
报错:Uncaught ReferenceError: Cannot access 'name' before initialization
为什么只有报错信息?按理说let变量如果存在变量提升则会输出一个undefined。
其实let变量的提升过程与其他不同,let变量提升过程是:
- 找到所有用 let 声明的变量,在环境中「创建」这些变量
- 开始执行代码console.log(name);(注意现在还没有初始化)
- 执行 let name;,将 name「初始化」为 undefined
- 执行name=“zzs”;,对 name进行「赋值」
程序在第二步已经出错,所以不在进行。
函数提升
<script type="text/javascript">
print();
function print(){
console.log("Tom");
};
</script>
上述代码中print函数可以成功调用,可见此种函数声明方式存在提升。
<script type="text/javascript">
print();
var print = function (){
console.log("Tom");
};
</script>
报错:“Uncaught TypeError: undefined is not a function”
实际上,此时声明方式为先声明变量 var print;然后定义一个匿名函数,将此匿名函数赋值给print,匿名函数不存在提升,所以,会报错。