技术实践

var、let 及 const 区别

var 存在提升,我们能在声明之前使用。let、const 因为暂时性死区的原因,不能在声明前使用 var 在全局作用域下声明变量会导致变量

羊先生的头像
羊先生2020.02.17 · 4 分钟阅读 · 165 阅读
var、let 及 const 区别封面
文章正文还需 4 分钟

对于这个问题,我们应该先来了解提升(hoisting)这个概念

var

js 复制代码
console.log(a) // undefined
var a = 1

从上述代码中我们可以发现,虽然变量还没有被声明,但是我们却可以使用这个未被声明的变量,这种情况就叫做提升,并且提升的是声明。

对于这种情况,我们可以把代码这样来看

js 复制代码
var a
console.log(a) // undefined
a = 1

当函数和变量重名,变量的提升更高,函数的提升在变量的下面

js 复制代码
var a = 10;
var a = function (){}
console.log(a) // ƒ (){}

var b = 20;
function b(){}
console.log(b) // 20

解读

js 复制代码
var a;
a = function (){};

var b;
function b(){};
b = 20;

函数提升

函数提升所指的形式:function fn(){......}(必须是函数声明的形式,不能是函数表达式的形式) 
所有使用function声明的函数,都会整体提升,只要当前作用域内声明了函数,在任何位置都可以使用,赋值式创建函数,提升的声明,不是。
当函数和变量重名,变量的提升更高,函数的提升在变量的下面

接下来我们再来看一个例子

js 复制代码
var a = 10
var a
console.log(a)

对于这个例子,如果你认为打印的值为 undefined 那么就错了,答案应该是 10,对于这种情况,我们这样来看代码

js 复制代码
var a
var a
a = 10
console.log(a)

到这里为止,我们已经了解了 var 声明的变量会发生提升的情况,其实不仅变量会提升函数也会被提升

js 复制代码
console.log(a) // ƒ a() {}
function a() {}
var a = 1

对于上述代码,打印结果会是 ƒ a() {},即使变量声明在函数之后,这也说明了函数会被提升,并且优先于变量提升

循环内变量过度共享

js 复制代码
for (var i = 0; i < 3; i++) {
      setTimeout(function () {
        console.log(i) // 3 3 3
      }, 1000);
}

for(var i=0;i<=10;i++){ 
  var sum=0; 
  sum+=i; 
} 
console.log(sum) // 10

let

let拥有块级作用域,一个{}就是一个作用域,也就是let声明块级变量,即局部变量;
let在其作用域下面不存在变量提升;
let在其作用域中不能被重复声明(函数作用域和块级作用域)

js 复制代码
let n = 10;  
if(true){  
    let n = 50;  
}  
console.log(n);//10  

let在同一个作用域下不允许进行重复变量声明,否则直接报错

js 复制代码
(function(){  
    let test1 = "let";  
    var test2 = "var"  
      
    let test1 = "let changed";//Uncaught SyntaxError: Identifier 'lTest' has already been declared  
    var test2 = "var changed";  
      
    console.log(test1);  
    console.log(test2);  
})();

const

const用来声明常量,一旦声明,其值就不可以更改,而且必须初始化

js 复制代码
var a = 1
let b = 1
const c = 1
const obj = {a:1}
obj.a = 10
console.log(window.a) // 1
console.log(window.b) // undefined
console.log(window.c) // undefined
console.log(obj.a) // 10 因为对象是引用类型 储存在堆中

总结

var 存在提升,我们能在声明之前使用。let、const 因为暂时性死区的原因,不能在声明前使用
var 在全局作用域下声明变量会导致变量挂载在 window 上,其他两者不会
let 和 const 作用基本一致,但是后者声明的基本类型变量不能再次赋值

更多相关文章

let和const
js中的函数提升和变量提升