Day19 var vs let 区别

97 阅读3分钟

每日一句

For the things that make you sad, one day, you will laugh out and say it.

释义:让你难过的事情,总有一天你会笑着说出来。

image.png

前言

var, let 在js中都是用来声明变量的,let是es6中新增出来的,为啥会出来let呢,var是有啥缺陷?

var

  • 声明的变量是全局的,且window顶层也能访问
  • 声明变量后还可以再声明(相同{}[作用域内]内会变量污染)
var a=1;
console.log(a); // 1
console.log(window.a); // 1
console.log(window['a']);  // 1
if (true) {
  // 重新定义了a
  var a = 8;
  console.log(a); //8
}
console.log(a) //8
  • 可以在变量声明前,使用变量(变量会提升)
console.log(a); // undefined
var a = 5;
  • 函数内声明的变量是局部变量,外层访问报错
(function() {
  var a = 888;
  console.log(a) // 888
})()
console.log(a);
  • 函数内不用声明也是全局变量(不建议,严格模式报错,es6警告)
(function(){
  a = 999
})()
console.log(a)
console.log(window.a)
console.log(window['a'])
  • 声明的全局变量可能会造成变量污染
for (var i=0; i<3; i++) {
  setTimeout(() => console.log(i), 0) // 3 3 3
}
console.log(i); // 3

let

  • 声明的全局变量,window顶层没有这个属性
  • 声明后的变量,在不同的{}中,只会在{}中生效
let a = 1;
console.log(a) // 1
console.log(window.a) // undefined
console.log(window['a']) // undefined
if (true) {
  // 重新定义
  let a = 8
  console.log(a) // 8
}
console.log(a) // 1
  • 声明后的变量,在相同的{}中,直接报错
let a = 1;
let a = 8;
console.log(a) // Uncaught SyntaxError: Identifier 'a' has already been declared
  • 未声明,先引用,报错
console.log(a); // Uncaught ReferenceError: a is not defined
let a = 9;
  • 函数内声明的变量是局部变量,外层访问报错
(function() {
  let a = 888;
  console.log(a) // 888
})()
console.log(a);
  • 声明的全局变量只会在{}生效,不会造成变量污染
for (let i=0; i<3; i++) {
  setTimeout(() => console.log(i), 0) // 0 1 2
}
console.log(i); // ReferenceError: i is not defined

总结

VAR VS LET

相同点:

  • 在js中都是用来声明变量,函数内声明是局部变量

  • 不在{}或函数内声明的变量是全局变量

不同点:

  • var声明的全局变量会顶层对象的属性,而let声明的变量不是顶层对象的属性

  • 非函数内,let声明的变量在{}中生效,{}之外不生效,而var声明的变量会生效

  • var声明的变量会提升,不会报错,而let声明的变量不会提长,报错

  • [非严格模式]var声明的变量可以重新声明,不会报错,其值是最后一次声明的值,而let不可以再次声明,会报错

从var与let的不同点出发,我们知道了为啥es6会出来let关键字,正因为var声明的变量可能潜在污染变量,给开发带来严重的影响,当然还有其他原因,进而es6推出let来声明。

扩展

顶层对象:浏览器的顶层对象是window,Node中的是global对象

ES5中的顶层对象的属性等价于全局变量。

ES6中,var function 声明的全局变量依然是顶层对象的属性; let const class import 声明的全局变量不属于顶层对象的属性。

也就是说ES6开始,全局变量和顶层对象的属性开始分离,脱钩。

ES5声明变量只有两种方式:var 和 function, var 变量提升, function 是提升 + 定义。

ES6 声明变量的方式有:let const  import  class 再加上ES5的var  function 一共是有6种声明变量的方式

const声明的变量不可以修改,而且必须初始化。