• js预编译(全局预编译/函数预编译)


    1.预编译

    预编译是上下文创建之后, js代码执行前的一段时期, 在这个时期, 会对js代码进行预处理

    2.全局预编译

    全局上下文创建后,会生成变量对象VO:var变量-》函数-》同名函数覆盖变量名

    1. VO首先寻找变量声明,将var声明的变量作为VO对象的属性名,值为undefined。
    2. 然后寻找函数声明,属性值为函数本身
    3. 如果函数名与变量名冲突,函数声明会将变量声明覆盖。
    1. function a(b, c) {
    2. console.log(b);
    3. var b = 0
    4. console.log(b);
    5. var b = function () {
    6. console.log('bbbb')
    7. }
    8. console.log(c);
    9. console.log(b);
    10. }
    11. a(1)

    全局预编译分析:

    1. // 第一步:寻找变量声明var,将变量名作为属性名,将值设置为undefined
    2. VO {
    3. a: undefined
    4. }
    5. // 第二步:寻找函数声明,属性值为函数本身
    6. // 第三步:函数名和变量名冲突,函数声明会覆盖变量声明
    7. VO {
    8. a: undefined-> function a() { }
    9. }
    10. //执行结果: function a() { }, 100

    3.函数预编译

    函数上下文创建后,会生成变量对象AO:函数预编译: var变量-》形参-》实参赋值给形参-》函数-》同名函数覆盖变量声明

    1. 寻找变量声明, 变量名作为AO对象的属性名, 属性值置为 undefined
    2. 寻找形参, 形参名作为AO对象的属性名, 属性值置为 undefined
    3. 将实参的值赋予形参, 即替换 AO对象中形参的属性值
    4. 寻找函数声明, 函数名作为AO对象的属性名, 属性值为函数本身
    5. 如果函数名与变量名冲突, 函数声明会将变量声明覆盖 

    注意:函数预编译时,如果有判断条件里面的变量声明,无论判断条件真假,都会进行预编译。

    如下:这里函数里面的var tmp也会进行预编译

    1. function a(b, c) {
    2. console.log(b);
    3. var b = 0
    4. console.log(b);
    5. var b = function () {
    6. console.log('bbbb')
    7. }
    8. console.log(c);
    9. console.log(b);
    10. }
    11. a(1)

    函数预编译解析:

    1. // 第一步:寻找函数中的变量声明,将变量名作为属性名,将值设置为undefined
    2. AO : {
    3. b: undefined,
    4. }
    5. // 第二步:寻找形参
    6. AO : {
    7. b: undefined,
    8. c: undefined,
    9. }
    10. // 第三步:将实参传给形参(b变成了1)
    11. AO : {
    12. b: undefined -> 1,
    13. c: undefined,
    14. }
    15. // 第四步:寻找函数声明(此处没有)
    16. // 第五步:如果函数名与变量名冲突, 函数声明会将变量声明覆盖(此处没有)
    17. // 执行结果:1 ,0,(将函数赋值给b),undefined, b的函数体

    4.全局预编译和函数预编译整个流程

    1. 全局预编译和局部预编译都有时,是先进行全局预编译,预编译完成后会逐行执行,比如一些变量赋值,打印;
    2. 函数预编译是在函数被调用前才进行预编译,编译完成后再开始执行;
    3. 执行是首先在自己作用域里面查找属性,有属性没有赋值直接返回undefined ,没有定义属性从全局查找,查找不到返回undefined

    5.预编译面试题

    1. // 面试题
    2. function fn(a, c) {
    3. console.log(a)
    4. var a = 123
    5. console.log(a)
    6. console.log(c)
    7. function a() { }
    8. if (false) {
    9. var d = 678
    10. }
    11. console.log(d)
    12. console.log(b)
    13. var b = function () { }
    14. console.log(b)
    15. function c() { }
    16. console.log(c)
    17. }
    18. fn(1, 2)

    预编译解析: 

    1. // 函数预编译: var变量-》形参-》实参赋值给形参-》函数-》同名函数覆盖变量声明
    2. AO:{
    3. a: undefined->1->funA,
    4. d: undefined,
    5. b: undefined-》funB,
    6. c: 2->funC
    7. }
    8. // 执行结果:funA,123,funC,undefined,undefined,funB,funC

  • 相关阅读:
    [架构之路-59]:目标系统 - 平台软件 - 基础中间件 - POSIX(可移植操作系统接口)与标准库函数libc
    git基础
    Vue中如何实现动态改变字体大小
    git分支管理以及不同git工作流对比
    字符串和内存函数
    笔记 vue3如何引入iconfont
    【项目实践-04】实验室移动端:对象添加新属性+webview IOS端appendJsFile()方法不生效
    信创之国产浪潮电脑+统信UOS操作系统体验2:安装visual studio code和cmake搭建C++开发环镜
    HTML5语义化标签 header 的详解
    Spring 中容器启动分析之refresh方法执行之前
  • 原文地址:https://blog.csdn.net/qq_34569497/article/details/133811829