变量提升和块级作用域
变量提升
JavaScript引擎的工作方式是先解析代码,获取所有被声明的变量,然后一行一行的执行。所有变量的声明语句被提升到代码的头部,这就叫变量提升。
实例1:
1 console.log(a); 2 var a = 1;
以上语句不会报错,只提示 undefined 。
实际运行过程:
1 var a; 2 console.log(a); 3 a = 1;
变量a已经声明,但还未赋值。
变量的提升只会对var命令声明的变量有效,其他不是用var命令声明的变量,不会发生变量的提升。
实例2:
1 console.log(a); 2 a = 1;
以上代码将会报错: ReferenceError: aa is not defined 。
与普通变量一样,js里面的 function 也可看做变量,也存在变量提升的情况:
实例3:
1 a(); 2 function a(){ 3 console.log(1); 4 }
表面上声明之前调用函数a。由于变量提升,函数a定义部分被提升到了代码头部,即调用之前已经声明。
采用赋值语句定义函数会报错 TypeError: a is not a function 。
实例4:
1 a(); 2 var a = function(){ 3 console.log(1); 4 };
以上代码会报错 TypeError: a is not a function
实际运行过程:
1 var a; 2 a(); 3 a=function(){ 4 console.log(1); 5 }
这个时候啊是个变量,并不是function。
块级作用域
let取代var
ES6提出的两个新的声明变量: let 和 const 。let可以完全取代var,两者语义差不多,let没有副作用。
console.log(x); // ReferenceError
let x = 'hello';
不会存在变量提升的问题,会在console.log那一行报错
在 let 和 const 建议优先使用const,尤其在全局环境,不应设置变量,只因设置常量。
为什么const优于let?
一、const可以提醒阅读程序的人这个变量不应该改变。
二、const比较符合函数式编程思想,运算不改变值,只是新建值,防止无意间修改变量值所导致的错误,而且这样也有利于将来分布式运算。
三、JavaScript编译器会对const进行优化。
多使用const,有利于提高程序的运行效率。
let
和const
的本质区别,其实是编译器内部的处理不同。