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
相关推荐
摸鱼仙人~21 分钟前
styled-components:现代React样式解决方案
前端·react.js·前端框架
sasaraku.1 小时前
serviceWorker缓存资源
前端
RadiumAg2 小时前
记一道有趣的面试题
前端·javascript
yangzhi_emo2 小时前
ES6笔记2
开发语言·前端·javascript
yanlele2 小时前
我用爬虫抓取了 25 年 5 月掘金热门面试文章
前端·javascript·面试
中微子3 小时前
React状态管理最佳实践
前端
烛阴4 小时前
void 0 的奥秘:解锁 JavaScript 中 undefined 的正确打开方式
前端·javascript
中微子4 小时前
JavaScript 事件与 React 合成事件完全指南:从入门到精通
前端
Hexene...4 小时前
【前端Vue】如何实现echarts图表根据父元素宽度自适应大小
前端·vue.js·echarts
初遇你时动了情4 小时前
腾讯地图 vue3 使用 封装 地图组件
javascript·vue.js·腾讯地图