JavaScript从入门到入土(3):预编译

预编译(通常称为 "变量提升")是 JavaScript 的一种特殊机制,发生在编译阶段的早期 。它会将变量和函数声明 "提升" 到当前作用域的顶部,但赋值不会提升

编译过程

v8 引擎读取到js代码后,先编译后执行

编译全局 ->执行全局(有函数) ->编译函数 ->执行函数 ->继续执行全局

函数体编译过程

  1. 创建函数的上下文执行对象
  2. 找形参和变量(包括函数表达式)声明,将形参和变量名作为对象的属性名,值为undefined
  3. 将实参和形参相统一
  4. 在函数体里面找函数声明(不管函数表达式),函数名作为上下文对象的属性名,值为函数体

全局编译过程

  1. 创建全局执行上下文对象
  2. 找变量声明,将变量名作为对象的属性名,值为undefined
  3. 在全局找函数声明,函数名作为上下文对象的属性名,值为函数体

练习

代码最后输出什么?

js 复制代码
function foo(a, b) {
  console.log(a);
  c = 0
  var c;
  a = 3
  b = 2
  console.log(b);
  function b() {}
  console.log(b);
}
foo(1)

编译全局

  1. 创建全局执行上下文对象
  2. 未找到变量声明
  3. 找到函数声明,建立对象属性foo,值为函数体

最后得到如下的全局执行上下文对象

js 复制代码
GLOBAL:{
    foo: 函数体
}

执行全局

执行foo(1),编译foo函数

编译函数

  1. 创建函数的上下文执行对象
  2. 找到形参a、b和变量变量声明c作为对象属性名,值为undefined
  3. 将实参和形参相统一,把实参1赋值给形参a
  4. 在函数体里面找到函数声明function b() ,建立对象属性b,值为函数体(因为已经存在属性b,所以将b的undefined属性改为函数体)。

最后得到如下函数的上下文执行对象

js 复制代码
FUNCTION:{
  a:/*undefined  ->*/ 1 
  b:/*undefined ->*/函数体
  c:undefined
}

执行函数

  1. 执行打印语句console.log(a);,在函数的上下文执行对象中找到属性a的值为1,则输出 1
  2. 执行赋值语句c = 0,将属性c的值改为0
  3. 执行赋值语句a = 3,将属性a的值改为3
  4. 执行赋值语句b = 2,将属性b的值改为2
  5. 执行打印语句console.log(b);,在函数的上下文执行对象中找到属性b的值为2,则输出 2
  6. 执行打印语句console.log(b);,在函数的上下文执行对象中找到属性b的值为2,则输出 2

因为全局只需执行一个函数,所以当函数执行完毕全局也执行完毕,至此整个程序的编译执行过程我们已经分析完成。

答案为 :

1

2

2

相关推荐
killerbasd13 小时前
牧苏苏传 我不装了 4/7
前端·javascript·vue.js
橘子编程14 小时前
JavaScript与TypeScript终极指南
javascript·ubuntu·typescript
叫我一声阿雷吧14 小时前
JS 入门通关手册(45):浏览器渲染原理与重绘重排(性能优化核心,面试必考
javascript·前端面试·前端性能优化·浏览器渲染·浏览器渲染原理,重排重绘·reflow·repaint
大家的林语冰15 小时前
《前端周刊》尤大开源 Vite+ 全家桶,前端工业革命启动;尤大爆料 Void 云服务新产品,Vite 进军全栈开发;ECMA 源码映射规范......
前端·javascript·vue.js
jiayong2315 小时前
第 8 课:开始引入组合式函数
前端·javascript·学习
天若有情67316 小时前
【C++原创开源】formort.h:一行头文件,实现比JS模板字符串更爽的链式拼接+响应式变量
开发语言·javascript·c++·git·github·开源项目·模版字符串
yuki_uix16 小时前
重排、重绘与合成——浏览器渲染性能的底层逻辑
前端·javascript·面试
止观止17 小时前
拥抱 ESNext:从 TC39 提案到生产环境中的现代 JS
开发语言·javascript·ecmascript·esnext
时寒的笔记17 小时前
js逆向7_案例惠nong网
android·开发语言·javascript
吴声子夜歌17 小时前
ES6——Generator函数详解
前端·javascript·es6