sqlcommand 执行多个储存过程是报错_JavaScript执行机制 - 变量提升

04b9ef9c22dde9e10b559be5c22a40b6.png

背景

首先让我们观察下面的代码,并猜测输出的结果

func()
console.log(string)
var string = '字符串'
function func() {
    console.log('Hello world')
}

按顺序执行的话

  • 第一行调用func函数时,func函数并没有被声明,应该报错。
  • 第二行在控制台打印string变量时,string变量也未被声明,也应该报错。

然而实际情况是

  • 第一行成功打印了hello world。
  • 第二行打印输出了undefined。

如果把第三行代码注释掉,此时第二行代码会报错。

至此我们可以得出三个结论:

  1. 在执行过程中如果变量未被声明,则会报错。
  2. 如果在一个变量被声明之前使用它,则它的值为undefined。
  3. 如果在函数被声明前调用它,函数可以被正确的运行。

变量提升

通过对上面代码的测试,我们发现在代码真正运行之前JavaScript引擎会预先处理好变量和函数的声明,这个过程就是变量提升(Hoisting)

所以原本的一行语句其实分为声明赋值两个步骤,而在代码分析的过程中,用于声明的代码会先被处理。则文章开头的代码可以被分成两个过程:

// 声明
var string = undefined
function func() {
    console.log('Hello world')
}

// 运行
func()
console.log(string)
string = '字符串'

JavaScript的执行过程

这里我们先把JavaScript从代码到运行分为两个阶段:编译运行

553b36d158920bacae4b10870d425708.png
编译和运行

一段代码在经过编译后,代码会被转换成执行上下文可执行代码

执行上下文

执行上下文(Execution context)是JavaScript执行一段代码时的执行环境。其中包含了this的指向变量环境词法环境

执行上下文分为三种类型:

  • 全局执行上下文:这是默认或者说基础的上下文,任何不在函数内部的代码都在全局上下文中。它会执行两件事:创建一个全局的 window 对象(浏览器的情况下),并且设置 this 的值等于这个全局对象。一个程序中只会有一个全局执行上下文。
  • 函数执行上下文:每当函数被调用时,就会创建一个函数上下文。不同的函数执行上下文不同,同一个函数被多次调用时,会产生多个执行上下文。
  • Eval函数执行上下文:不常使用,这里不做介绍。

我们可以把执行上下文想象这如下这种结构:

ExecutionContext = {
  ThisBinding = <this value>, // this的指向
  LexicalEnvironment = { ... }, // 词法环境
  VariableEnvironment = { ... }, // 变量环境
}

所以在func函数被调用前执行上下文被创建后,其结构如下:

GlobalExectionContext = {

  ThisBinding: <Global Object>,

  LexicalEnvironment: { ... },

  VariableEnvironment: { // 变量环境
    EnvironmentRecord: {
      Type: "object",
      // 在这里绑定标识符
      string: undefined, // 默认值
      func: < func > 
    }
    outer: <null>
  }
}

FunctionExectionContext = {
  ThisBinding: <Global Object>,

  LexicalEnvironment: { ... },

  VariableEnvironment: {
    EnvironmentRecord: { ... },
    outer: <GlobalLexicalEnvironment>
  }
}

代码在执行后,执行上下文会变成:

GlobalExectionContext = {

  ThisBinding: <Global Object>,

  LexicalEnvironment: { ... },

  VariableEnvironment: { // 变量环境
    EnvironmentRecord: {
      Type: "object",
      // 在这里绑定标识符
      string: "字符串", // 赋值语句生效
      func: < func >
    }
    outer: <null>
  }
}

总结

至此,我们由JavaScript中的变量提升引出了JavaScript的执行上下文概念。

  • 在代码中使用var, function定义的变量将会被执行上下文记录在变量环境中。
  • 由var,function定义的的变量会在执行上下文创建的时候被声明及赋予默认值(var与function不同)。
  • 可执行代码在运行时会从执行上下文中读取变量,如果在修改前访问,则读取其默认值。
  • 如果变量提升过程中存在同名变量,则后一个会覆盖前一个。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值