一. 首先我么先来谈谈var吧,这是在es6出现之前常用的命名变量的方式
1. var声明作用域
function test(){
var msg = "var 声明作用域"
}
test();
console.log(msg); // 出错!!
msg是使用var关键字在test函数中定义的,调用test函数时会创建变量,并给它赋值,调用函数之后随即销毁变量,所以在函外部打印msg会报错。也就是说var声明的变量是函数级变量。
不过,如果在函数内部声明变量时省略var,就可以创建一个全局变量:
function test(){
msg = "var 声明作用域"
}
test();
console.log(msg); // 打印:var 声明作用域
去掉var操作符之后,只要调用一次test函数,就会创建一个全局的msg变量,因此,在函数外部调用时就可以获取到变量的值。
2. var 声明变量提升
使用var时,下面的代码不会报错,是因为使用var关键字声明的变量会自动提升到作用域的顶部
function foo () {
console,log(name)
var name = "Lally"
}
foo(); // 打印:undefined
之所以不会报错,是在运行的时候把它看成了等价于一下的代码:
function foo () {
var name;
console,log(name)
var name = "Lally"
}
foo(); // 打印:undefined
所谓提升,也就是把所有变量声明都拉到函数作用域的顶部,因此反复声明同一个变量也是没有问题的:
function foo () {
var name = "Lally"
var name = "rose"
var name = "zhangzhang"}
foo(); // 打印:zhangzhang
二. let 声明变量
1. let 声明作用域
// let 声明变量
if(true){
let age = 26;
console.log(age); // 打印: 26
}
console.log(age); // ReferenceError age 没有定义
// var 声明变量
if(true){
var age = 26;
console.log(age); // 打印: 26
}
console.log(age); // 打印: 26
使用let声明变量,在if条件外调用会报错,因为let声明的变量仅在if的块内生效,也就是let是块级作用域
使用var声明变量在if条件外调用就会正常运行,也证明了var声明的变量的作用域是函数级的。
2. 暂时死去
刚刚我们说过var声明的变量可以变量提升,但是let却没有提升这个本领
function foo () {
console,log(name)
let name = "Lally"
}
foo(); // ReferenceError name没有定义
如果在没有声明name之前都用了变量,就会报错,这也就是所谓的let的"暂时死区"。因为let声明的变量不会在作用域中被提升。
3. 全局声明
与var关键字不同,使用let在全局声明的变量不会成为window对象的属性(var声明的则会)
var name = "lally";
console.log(name); // 打印:lally
let name = "lally";
console.log(name); // undefined
不过,let声明任然是在全局作用域中发生的,相应的变量会在页面生命周期中存续,因此为了避免 SyntaxError,就要确保页面不会重复声明同一个变量
在let之前,使用var在for循环中声明变量,会迭代渗透到循环体外部:
for(var i = 0;i<5; i++){
// 循环逻辑
}
console.log(i) ; // 5
使用let则解决了这个问题,因为let迭代的变量作用域仅限于for循环块内
for(let i = 0;i<5; i++){
// 循环逻辑
}
console.log(i) ; // ReferenceError i没有定义
3. const 声明
其实const与let声明是基本相同的,唯一一个重要的区别的就是const声明变量时必须同时初始化变量,并且尝试修改const声明的变量会导致运行错误
const age = 26;
age = 27; // TypeError:给常量赋值
const 也不允许重复声明
const age = 26;
const age = 27; // SyntaxError
同样 const 作用域也是块级
在实际应用中var,let,const使用的优先级又是如何的呢:
1. 尽量不适用var声明
有了let和cosnt,会有助于提升代码的质量,因为变量有了明确的作用域,声明位置以及不变的值
2. const 优先,let次之
使用const 可以让浏览器运行时,强制变量不变,也可以让静态代码工具提前发现不合理的操作。在提前知道变量未来会有修改时再使用let声明变量。