ES6 var + let + const 和 代码块

特性 var let const
作用域 函数作用域 / 全局作用域 块级作用域 块级作用域
提升 提升并初始化为 undefined 提升但不初始化 (TDZ) 提升但不初始化 (TDZ)
重复声明 允许 不允许 不允许
重新赋值 允许 允许 不允许
声明时初始化 可选 可选 必须
全局对象属性 是 (全局作用域)

1. 最基本的区别

var VS let + const

var 能够重复声明变量
js 复制代码
var name = 'why'
console.log(name) //why
var name = 'wei'
console.log(name)//wei
let 不能够重复声明相同的变量

会报错

const 不能够重复声明相同的变量

var let VS const

var 和 let 能够改变声明变量, const不能改变声明的变量
js 复制代码
var ageVar = 18
console.log(ageVar) //18
ageVar = 19
console.log(ageVar) //19

let ageLet = 88
console.log(ageLet) //88
ageLet = 99
console.log(ageLet) //99

const不能重复声明

js 复制代码
const ageConst = 188
console.log(ageConst)
ageConst = 111
console.log(ageConst) //报错

2. 对对象的相同点和不同点

对于var
js 复制代码
var obj1 = {
  name: 'why',
  age: 18
}
console.log(obj1)//{ name: 'why', age: 18 }
obj1.name = 'wei'
console.log(obj1)//{ name: 'wei', age: 18 }

 obj1 = {aa: 'aa'}
console.log(obj1)//{ aa: 'aa' }
对于let
js 复制代码
let  obj1 = {
  name: 'why',
  age: 18
}
console.log(obj1)//{ name: 'why', age: 18 }
obj1.name = 'wei'
console.log(obj1)//{ name: 'wei', age: 18 }


obj1 = {aa: 'aa'}
console.log(obj1)//{ aa: 'aa' }
对于const
js 复制代码
const obj1 = {
  name: 'why',
  age: 18
}
console.log(obj1)//{ name: 'why', age: 18 }
obj1.name = 'wei'
console.log(obj1)//{ name: 'wei', age: 18 }

//会报错❌
obj1 = {aa: 'aa'}
console.log(obj1)//{ aa: 'aa' }

3. let 和 const 的作用域提升

js 复制代码
console.log(nameVar)// undefined
var nameVar = 'why'

//error
console.log(nameLet)
let nameLet = 'why'

//error
console.log(nameConst)
const nameConst = 'why' 
  1. 当使用var let const创建变量时,他们的声明的变量都会被创建出来
  2. 但不同的是。var创建的变量是可以被访问的,而let 和 const 创建的的变量是不能够被访问
  3. let和const的变量直到赋值时对变量进行绑定,才能够进行访问
我们得出结论

作用域提升:在上面变量的作用域中,如果这变量可以在声明之前被访问,那么我们称为作用域提升

let 和 const:他们和var一样变量名在声明时被创建出来了,但是不能被访问,不能称为作用域的提升

4. 与 window的关系 + 存放地址

Google的V8不能处理JavaScript中window的,window是在浏览器中进行处理的,包括window的一些属性(Date, Number)

  1. var 在全局作用域中声明的变量:

    • 存储位置: 这些变量被存储为全局对象 (在浏览器环境中是 window 对象,在 Node.js 中是 global 对象)的属性
    • 机制: 当 JavaScript 引擎处理全局作用域时,它会为 var 声明的变量在全局对象的属性集合中创建相应的条目。这就是为什么你可以通过 window.yourVarName (浏览器) 或 global.yourVarName (Node.js) 来访问全局 var 变量。它们与全局对象的生命周期绑定。
  2. let 和 const 在全局作用域中声明的变量:

    • 存储位置: 这些变量被存储在一个与全局对象不同的、独立的词法环境(Lexical Environment)中。这个环境通常被称为"脚本作用域" (Script Scope) 或顶层词法环境。它们会成为全局对象的属性。
    • 机制: ES6 引入了块级作用域和 let/const,其设计目标之一是减少对全局对象的污染。因此,规范规定全局的 let 和 const 变量存储在脚本自身的顶级作用域记录中,而不是直接附加到 window 或 global 对象上。这个脚本作用域存在于全局作用域链的最顶层,使得这些变量仍然是全局可访问的(在声明之后且脱离 TDZ),但它们与全局对象解耦了。

简单来说:

  • 全局 var → 住在 window (或 global) 这栋大楼里,成为大楼的一个房间(属性)。
  • 全局 let / const → 也住在这片区域(全局作用域),但它们住在自己独立的房子(脚本作用域/顶层词法环境)里,不属于 window 大楼。

为什么要知道这个区别?

  • 避免全局污染: 使用 let 和 const 可以让你的全局变量不直接干扰 window 对象,减少了意外覆盖 window 内置属性或被其他库覆盖的风险。
  • 理解访问方式: 你不能通过 window.myLetVariable 来访问全局 let 变量,必须直接使用 myLetVariable。
  • 模块化思维: 这更符合现代 JavaScript 的模块化开发模式,每个脚本或模块可以在其顶层作用域中拥有自己的变量,而不会轻易干扰其他模块或全局环境。
js 复制代码
var globalVar = 'var on window';
let globalLet = 'let in script scope';
const globalConst = 'const in script scope';

console.log(window.globalVar);   // 'var on window'
console.log(window.globalLet);   // undefined
console.log(window.globalConst); // undefined

console.log(globalVar);          // 'var on window'
console.log(globalLet);          // 'let in script scope'
console.log(globalConst);        // 'const in script scope'

let 和 const 的暂时性死区(TDZ)

在代码中,使用let 和 const 声明变量,在声明变量之前,变量都是不可以访问的, 我们称这种现象为暂时性死区(TDZ)

经常出现在if条件语句函数语句

在 if 中
js 复制代码
var foo = 'foo'

if (true) {
  console.log(foo) //foo
}

下面的代码会报错,触发了暂时性死区(TDZ)

js 复制代码
var foo = 'foo'

if (true) {
  console.log(foo)

  let foo = 'abc'
}
在 function 中
js 复制代码
var foo = 'foo'
function bar () {
  console.log(foo)
}
bar() //foo

下面的代码会报错,触发了暂时性死区(TDZ)

js 复制代码
var foo = 'foo'
function bar () {
  console.log(foo)
  let foo = 'abc'
}
bar()

代码块

声明字面量

js 复制代码
var obj = {
  name: 'why'
}

什么时候选择var let const

  • var 由于历史的特殊性:作用域提升,window全局对象,没有块级作用域等历史遗留问题 目前不推荐使用var
  • 在开发中推荐使用let const ,我们优先使用const,可以保证数据的安全性,不会被随意的的篡改。当我们明确的知道变量后续需要被重新赋值的时候,再使用let

代码块

js 复制代码
{
  var foo = 'foo'
}

ES5中只有两个东西会形成块级作用域

在es5中没有块级作用域
  1. 全局作用域
  2. 函数作用域

函数作用域中通过函数链,可以访问外部的变量

当有函数嵌套时,也是同样的道理,内部的函数可以通过函数链访问到外部的变量,而外部的不能够访问内部的变量

ES6 块级作用域

代码块对var不起作用,其他起作用
js 复制代码
{
  var foo = 'foo'
  let bar = 'bar'
  const bar1 = 'bar1'
  
  class Person {}
}
console.log(foo) //foo

console.log(bar) //error
console.log(bar1) //error
var p = new Person() //error
函数在代码块中的特殊表现
js 复制代码
{
  function demo () {
    console.log('demo function')
  }
}
demo() //demo function

为什么会这样,不是说代码块中外部无法访问吗❓ 答:不同的浏览器有不同的实行,大部分浏览器为了兼容以前的代码,让function是没有块级作用域的

常见的块级作用域

1. if语句
js 复制代码
if (true) {
  var foo = 'foo'
  let bar = 'bar'
  const bar1 = 'bar1'
}

console.log(foo) //foo ✔️
console.log(bar) //error
console.log(bar1) //error
2. switch语句
js 复制代码
var color = 'red'

switch(color) {
  case 'red':
    var foo = 'foo'
    let bar = 'bar'
    const bar1 = 'bar1'
}

console.log(foo) //foo 
console.log(bar) //error
console.log(bar1) //error
3. for循环语句

var 在for语句中

js 复制代码
for (var i = 0; i < 1; i++) {
  console.log(`hello ${i}`)
}

console.log(i)

//hello 0
//1

let (const)在for语句中

js 复制代码
for (let  i = 0; i < 1; i++) {
  console.log(`hello ${i}`)
}

console.log(i) //error

//hello 0
相关推荐
东东2334 分钟前
前端开发中如何取消Promise操作
前端·javascript·promise
掘金安东尼9 分钟前
官方:什么是 Vite+?
前端·javascript·vue.js
柒崽11 分钟前
ios移动端浏览器,vh高度和页面实际高度不匹配的解决方案
前端
渣哥27 分钟前
你以为 Bean 只是 new 出来?Spring BeanFactory 背后的秘密让人惊讶
javascript·后端·面试
烛阴35 分钟前
为什么游戏开发者都爱 Lua?零基础快速上手指南
前端·lua
大猫会长1 小时前
tailwindcss出现could not determine executable to run
前端·tailwindcss
Moonbit1 小时前
MoonBit Pearls Vol.10:prettyprinter:使用函数组合解决结构化数据打印问题
前端·后端·程序员
533_1 小时前
[css] border 渐变
前端·css
云中雾丽1 小时前
flutter的dart语言和JavaScript的消息循环机制的异同
前端
地方地方1 小时前
Vue依赖注入:provide/inject 问题解析与最佳实践
前端·javascript·面试