前言:
是,我们老在用let
、const
和var
。但你非得说的话,那它们到底有啥不一样的?
在JavaScript中,let
、const
和var
都是用于声明变量的关键字,它们有一些重要的差异。这些差异主要体现在作用域(scope)、变量提升(hoisting)、可变性(mutability) 和全局对象属性等方面。以下是对它们之间差异的详细说明:
作用域:
1.全局作用域(Global Scope):
- 在函数之外用
var
、let
或const
声明的变量都具有全局作用域,这些变量可以在任何地方被访问和修改,包括函数内部。 - 在浏览器环境中,全局作用域的全局对象是window,在Node.js中是global。
2.函数作用域(Function Scope) :
- 函数作用域是指在函数内部定义的变量,这些变量只能在函数内部访问。
- 使用
var
声明的变量具有函数作用域。
3.块级作用域(Block Scope) :
- 块级作用域是指在块(由
{}
包围的代码块)内部定义的变量,这些变量只能在块内部访问。 - 使用
let
和const
关键字声明的变量具有块级作用域。
变量提升(Hoisting):
- js引擎在执行js的过程中把变量声明部分和函数声明部分提升到代码头部,默认赋值为
undefined
。 - 声明提升是发生在编译阶段。
var
有变量提升,let
和const
没有。
可变性(Mutability):
var
和let
:声明的变量可以重新赋值。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对象上添加了一个属性。let
和const
:在全局作用域中声明的变量不会成为全局对象的属性。
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()
能将原本不属于这里的代码变成就像天生就定义在这里一样。
with()
with()
用于修改一个对象中的属性值,但如果修改的属性在原对象中不存在,那么该属性就会被泄露到全局。
正常修改:
属性泄露到全局:
总结
- 作用域:
var
有函数作用域,而let
和const
有块级作用域。 - 变量提升:
var
变量提升并初始化为undefined
,let
和const
变量提升但不初始化,在实际声明前使用会导致错误。 - 可变性:
var
和let
声明的变量可以重新赋值,而const
声明的变量不能重新赋值(但对象和数组的内容可以修改)。 - 全局对象属性:在全局作用域中,
var
声明的变量会成为全局对象的属性,而let
和const
不会。 - 可以通过
eval()
和with()
达到欺瞒词法作用域的作用。
因此建议在现代JavaScript开发中优先使用let
和const
,以避免传统var
带来的作用域问题和潜在的错误。