var、let和const

变量提升

var 的变量提升

使用var声明的变量,存在变量提升(hoisting)。

console.log(a) // undefined
var a = 1

虽然a还没有声明,但是我们可以使用这个变量。我们可以把代码这样看:

var a;
console.log(a) // undefined
a = 1

变量的声明被提升到了开头。注意,提升的是变量声明而不是变量赋值。

在函数中用var声明的变量会提升到函数开头。

此外,函数也存在提升。function声明的函数,整个函数定义都会被提升。并且,函数的提升是优于变量的提升的。

sayHi("JavaScript"); // "Hello, JavaScript"

// 函数提升是优于变量提升
// var sayHi = 'sayHi'; // SyntaxError: Identifier 'sayHi' has already been declared

function sayHi(name) {
console.log(`Hello, ${name}`)
}


函数sayHi可以在声明语句前被使用。

注意,以下方法定义函数的话达不到这种效果:

bye("JavaScript"); // Uncaught TypeError: bye is not a function

var bye = function(name) {
console.log(`Good bye, ${name}`)
}

原因也是var变量声明会被提升,以上代码相当于:

var bye; // bye 为 undefined
bye("JavaScript"); // Uncaught TypeError: bye is not a function
bye = function(name) {
console.log(`Good bye, ${name}`)
}

let和const没有变量提升

console.log(a); // ReferenceError: Cannot access 'a' before initialization
let a = 1;

let语句声明a之前,我们是不可以用这个a的,否则会报错。

重复声明

由于var变量声明存在提升,因此var可以重复声明变量:

var a = 1;
var a = 10;
var a;
console.log(a); // 结果是10,而不是undefined

// 相当于:
var a;
var a;
a = 10;

letconst不能重复声明。

作用域

var只有两种作用域:全局作用域和函数作用域。

letconst出现之前,程序员都是用立即执行函数(IIFE)来模拟块级作用域的。

(function() {
var message = "Hello";
alert(message); // Hello
})();
// 外部访问不到message,因为函数执行完成之后,这块内存就被释放了

letconst还有块级作用域——包括代码块{}if-elsefor语句。

总结

varletconst的区别是:

  1. var声明的变量,可以在其声明语言前被使用;letconst需要先声明再使用。

  2. var可以重复声明,letconst不能重复声明;

  3. var只有全局作用域和函数作用域,letconst还有块级作用域;

  4. var 在全局作用域下声明变量会导致变量挂载在 window 上,其他两者不会

  5. let声明的变量复制后值能改变,const声明的变量赋值后不能再改。

Author: kpt

Permalink: http://kpt.ink/2021/08/26/var-let-const/

文章默认使用 CC BY-NC-SA 4.0 协议进行许可,使用时请注意遵守协议。