JS: 这let、const、var 能有啥不一样的

860 阅读3分钟

前言:

是,我们老在用letconstvar。但你非得说的话,那它们到底有啥不一样的?

在JavaScript中,letconstvar都是用于声明变量的关键字,它们有一些重要的差异。这些差异主要体现在作用域(scope)变量提升(hoisting)可变性(mutability)全局对象属性等方面。以下是对它们之间差异的详细说明:

作用域:

1.全局作用域(Global Scope):

  • 函数之外 varletconst 声明的变量都具有全局作用域,这些变量可以在任何地方被访问和修改,包括函数内部。
  • 在浏览器环境中,全局作用域的全局对象是window,在Node.js中是global。
1718716427585.png

2.函数作用域(Function Scope) :

  • 函数作用域是指在函数内部定义的变量,这些变量只能在函数内部访问。
  • 使用 var 声明的变量具有函数作用域。

1718718502752.png

3.块级作用域(Block Scope) :

  • 块级作用域是指在块(由 {} 包围的代码块)内部定义的变量,这些变量只能在块内部访问。
  • 使用letconst关键字声明的变量具有块级作用域。

1718719585642.png

变量提升(Hoisting):

  • js引擎在执行js的过程中把变量声明部分和函数声明部分提升到代码头部,默认赋值为undefined
  • 声明提升是发生在编译阶段。
  • var 有变量提升,letconst 没有。

1718721792849.png

可变性(Mutability):

  • varlet:声明的变量可以重新赋值。
  • const:定义的为常量,不可重新赋值。但对于对象和数组,可以修改其内容。
var d = 40;
d = 50; // 允许 

let e = 60; 
e = 70; // 允许
const f = 80;
f = 90; // 报错: Assignment to constant variable.

const obj = { key: 'value' };
obj.key = 'newValue'; // 允许,修改对象的属性
console.log(obj.key); // 输出 'newValue'

全局对象属性:

  • var:在全局作用域中,通过var声明的变量相当于是在window对象上添加了一个属性。
  • letconst:在全局作用域中声明的变量不会成为全局对象的属性。
var g = "hello";
console.log(window.g); // 输出 "hello"
let h = "world";
console.log(window.h); // 输出 undefined

const i = "!";
console.log(window.i); // 输出 undefined

小知识:欺骗词法作用域:

eval()

eval()能将原本不属于这里的代码变成就像天生就定义在这里一样。

1718771787242.png

with()

with()用于修改一个对象中的属性值,但如果修改的属性在原对象中不存在,那么该属性就会被泄露到全局。

正常修改:

1718772073555.png

属性泄露到全局:

1718772464972.png

总结

  • 作用域:var有函数作用域,而letconst有块级作用域。
  • 变量提升:var变量提升并初始化为undefinedletconst变量提升但不初始化,在实际声明前使用会导致错误。
  • 可变性:varlet声明的变量可以重新赋值,而const声明的变量不能重新赋值(但对象和数组的内容可以修改)。
  • 全局对象属性:在全局作用域中,var声明的变量会成为全局对象的属性,而letconst不会。
  • 可以通过eval()with()达到欺瞒词法作用域的作用。

因此建议在现代JavaScript开发中优先使用letconst,以避免传统var带来的作用域问题和潜在的错误。