var变量提升

概要

原本只是想复习一下变量提升的知识,没想到引发了一系列知识点出来,什么执行上下文、环境记录、词法环境、变量环境。。。真滴是活到老学到老。

理清执行上下文、作用域、环境记录、词法环境等概念:https://blog.youkuaiyun.com/comedyking/article/details/119722561

先看下什么是变量提升

变量提升 指的是 js代码执行过程中,js引擎把变量声明部分和函数声明部分提升到作用域顶端,并设置默认值undefined

showName()
console.log(name) // undefined
var name = 'fhh'
function showName() {
  console.log('showName')
}

相当于

function showName() {
  console.log(name)
}
var name
showName() // showName
console.log(name) // undefined
name = 'fhh'

并且函数提升优先级高于变量提升。

function test() {
  console.log(name) // 打印function
  var name = 'test' // 
  function name() {}
  return name 
}
console.log(test()) // test

 如果变量同时发生变量提升和函数提升,函数提升优先级高于变量提升,并且不会将变量覆盖为undefined。 这段代码可以理解为

function test() {
  function name() {}
  console.log(name) // 打印function
  name = 'test'
  return name 
}
console.log(test()) // test

 

变量提升的问题

  • 变量容易在不被察觉的情况下覆盖掉
var name = 'window'
function shoName() {
  console.log(name)
  if(false) {
    var name = 'false'
  }
}
showName() // undefined
  • 本应该销毁的变量没有被销毁
for(var i = 0; i<5; i++){
  ...
}
console.log(i)

 

为什么会出现变量提升,先来看看js代码执行流程

  • 代码执行分为编译阶段和执行阶段(当执行全局代码 遇到函数时,也会先对函数进行编译,然后再执行)
  • 编译阶段:
    • js代码经过编译后,会生成两部分内容:执行上下文和可执行代码
    • 创建执行上下文由三部分组成:即This Binding、VariableEnvironment(变量环境组件)、LexicalEnvironment(词法环境组件)
      • This Binding即this的指向
      • 变量环境组件VariableEnvironment 保存着 var声明的变量和函数function、并且变量初始化值为undefined
      • 词法环境组件Lexical Environment 保存着let、const声明的变量和函数
    • js引擎会把声明以外的代码编译为字节码,作为可执行代码
  • 执行阶段:
    • 执行代码时,遇到变量或者函数,会到执行上下文所保存的变量环境组件VariableEnvironment 或者LexicalEnvironment词法环境组件查找

变量提升原理

可以看到所谓的变量提升,其实只是变量创建的过程 和 真实赋值的过程不同步带来的错觉, 因为在代码编译阶段已经把变量初始化好了,并且即使是let和const声明的变量也会进行变量提升,不过会多形成一个暂时性死区和块作用域

暂时性死区

let、const声明的变量 也在编译时创建,即亦会出现变量提升的情况,但是在代码未执行到 变量初始化之前 对变量进行访问或者赋值就会报错,所以变量初始化之前的代码叫暂时性死区。例如下面的代码会直接抛出错误

{
  var a = 1
  let a = 1 
}
{
  function a(){}
  let a = 1 
}

总结

  • 变量提升的原因是js代码在编译过程中已经对var声明的变量和function函数进行初始化。所以变量提升的本质,其实只是变量创建的过程 和 真实赋值的过程不同步带来的错觉
  • let、const声明的变量也会进行变量提升,但是会形成暂时性死区,所以在执行到赋值代码之前,访问变量的话会报错
  • 关于执行上下文和环境变量可以看这里:https://blog.youkuaiyun.com/comedyking/article/details/119722561
<think>好的,我现在需要回答用户关于var变量提升的问题。首先,我得回忆一下变量提升的概念。var声明的变量会被提升到其作用域的顶部,但赋值操作不会提升。也就是说,在声明之前使用变量不会报错,但值是undefined。 然后,我需要举个例子来说明。比如,在函数内部用var声明变量,在声明前打印的话,结果是undefined。而如果没有声明直接使用,会报错ReferenceError。 接下来,用户可能需要了解变量提升的具体表现,比如函数作用域内的提升,以及和let、const的区别。需要强调var提升是声明提升,赋值不提升,而let和const有暂时性死区,不会被提升到作用域顶部可用。 现在,我需要组织语言,先解释变量提升的定义,然后用例子说明,最后对比其他声明方式。确保回答清晰易懂。 然后,按照要求,在回答末尾提出3-5个相关问题。这些问题应该围绕var变量提升的关键点,比如与let的区别、函数作用域中的提升、赋值是否提升、实际开发中的注意事项等。 检查是否符合格式要求,确保相关问题部分正确输出,没有换行分散。 </think> 在JavaScript中,使用`var`声明的变量会经历**变量提升(Hoisting)**,这是JavaScript引擎在代码执行前的预解析阶段完成的机制。具体表现为:变量的声明会被“提升”到其所在作用域(函数作用域或全局作用域)的顶部,但**赋值操作不会被提升**。 ### 示例说明 ```javascript console.log(a); // 输出 undefined(声明被提升,但赋值未执行) var a = 10; // 等价于:var a; console.log(a); a = 10; ``` 上述代码中,`var a`的声明会被提升到当前作用域顶部(即`console.log(a)`之前),因此不会报错,但此时`a`尚未被赋值,所以值为`undefined`。若未使用`var`声明直接使用变量(如`console.log(b)`),则会抛出`ReferenceError`。 ### 关键特点 - 仅声明被提升,赋值保留在原位置。 - 作用域是函数作用域(全局作用域或函数内部),而非块级作用域(如`if`、`for`块)。 - 重复声明`var`变量不会报错(后声明会覆盖前声明,但赋值会保留最后一次操作)。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值