文章目录

  • JS引擎都做了什么?
    • 函数声明提升
    • var关键字的声明提升,赋值不提升
    • 一个奇奇怪怪的例子
    • 暗示全局变量
  • AO对象
  • GO对象
  • AO和GO综合练习

JS引擎都做了什么?

1.检查通篇的语法错误(语法分析)
1.5预编译的过程(预编译)
2.解释一行执行一行(解释执行)

函数声明提升

text();
function text() { console.log(1); } // 1

var关键字的声明提升,赋值不提升

var关键字声明的变量会自动提升到函数作用域顶部

所谓的“提升”(hoist),也就是把所有变量声明都拉到函数作用域的顶部。

此外,反复多次使用 var 声明同一个变量也没有问题。

console.log(a) // Uncaught ReferenceError: a is not defined
console.log(a);
var a; // undefined
console.log(a);
var a = 10; // undefined
// 提升的仅仅是变量的声明而不是初始化

undefined和error不一样!!!

一个奇奇怪怪的例子

console.log(a);
function a(a) {var a = 10;var a = function () {}
}
var a = 1;// 打印结果竟然不是undefined!
//    ƒ a(a) {//        var a = 10;
//        var a = function () {//
//        }
//    }

暗示全局变量

预编译有个特点:任何变量,如果未声明就赋值,那该变量为全局变量,即暗示全局变量(imply global)。并且所有的全局变量都是window的属性。

var a = 1;
b = 2;
console.log(window.b); // 1
console.log(window.a); // 2
// var操作符在全局作用域下声明的变量自动变为window的对象 如a
// 在函数内定义变量时省略var会创建全局变量 如b
function test() {var a = b = 2;
}
test();
console.log(b); // 2
console.log(a); // Uncaught ReferenceError: a is not defined
console.log(window.a); // undefined
// 函数体先声明了一个局部变量a,然后不使用var声明了一个全局变量b,将b赋初值为2,最后用b的值初始化a
// 因此b作为全局变量在函数test()外部仍能访问
// a作为局部变量,只有函数作用域
// window对象打印不存在的属性时显示undefined
// 在第二局console报错时不会继续向下执行了,所以注释掉这一句

AO对象

AO对象全称为:activation object (活跃对象/执行期上下文/函数上下文),在函数执行前执行函数预编译,此时会产生一个AO对象,AO对象保存该函数的参数变量。

函数预编译步骤:

  1. 产生空的AO对象
  2. 找形参和变量声明,作为AO对象的属性名,值为undefined。
  3. 实参值赋值给形参。
  4. 在函数里面寻找函数声明,函数名作为AO对象的属性名(若形参、变量声明与函数名重叠,则函数体值会覆盖参数值与undefined),值为函数体。

执行

// eg.1
function test(a) {console.log(a);var a = 1;console.log(a);function a() { };console.log(a);var b = function () { };console.log(b);function d() { };
}
test(2);
  1. 创建AO对象
    AO{
    //此时AO对象为空
    }

  2. 确定AO对象的属性名
    e.g.1AO{
    a:undefined; //函数参数
    b:undefined; //函数里面声明的变量
    }

  3. 将实参值赋值给形参
    AO{
    a:undefined ->

    ​ 2 -> //函数参数
    b:undefined; //函数里面声明的变量
    }

  4. 处理函数里面的声明函数
    AO{
    a:undefined ->

    ​ 2 ->

    ​ function a () {} -> //函数声明提前,变量名一样,值覆盖

    ​ 1,

    b:undefined ->

    ​ function (){}, //函数里面声明的变量
    d:function d () {}
    }

此时函数预编译已经完成的,预编译后执行代码:
第一条执行的是控制台打印出a的值,所以输出function a () {};
第二条语句赋值给a,则AO对象中a的值被覆盖为2;
第三条语句控制台打印a的值为1;
第四条为声明,预编译处理过所以直接跳过
第五条打印出a的值,一样为1;
第六条为赋值,赋值b的值为function () {};
第七条打印出b的值function () {};
第八条声明,预编译处理过所以直接跳过;

所以输出结果应该是
function a () {};
1;
1;
function () {};
执行效果如图:

// eg.2
function test(a, b) {console.log(a);c = 0;var c;a = 5;b = 6;console.log(b);function b() { };function d() { };console.log(b);
}
test(1);AO = {a: undefined ->1 -> // 此时打印第一个console5,b: undefined ->function b() { } ->6, // 此时打印第二个console,并且由于下面对b()的函数声明//在预处理时做过了,直接pass,第三个console也输出这个bc: undefined ->0,d: function d() { },}

GO对象

GO对象全称为 global object(全局对象,等同于window),在开始预编译时产生的对象,比AO对象先产生,用于存放全局变量,也称为全局作用域。

预编译之前进行

  1. 生成空的GO对象
  2. 将变量声明的变量名当做GO对象的属性名,值为undefinded
  3. 将声明函数的函数名当做GO对象的属性名,值为函数体
console.log(a);
var a = 123;
function a() {}
console.log(a);
// GO: {//     a: undefined ->
//         function a() { } -> // 此时执行第一句console,预编译结束
//         123, //此时执行第二句console
// }

AO和GO综合练习

1.求输出结果

console.log(a); // undefined
a = 100;
function test() {console.log(a); // undefineda = 200;console.log(a); // 200var a = b = 300;
}
test();
console.log(b); // 300
var a;
console.log(a); //100
GO: {a: undefined ->100,function test() { },    b: undefined ->300,
}
AO: {a: undefined ->200 ->300,
}
  1. 生成GO对象
    GO{
    }

  2. 将声明变量添加进GO对象内,值为undefined
    GO{
    a:undefined;
    }

  3. 将声明函数添加进GO对象呢,值为函数体
    GO{
    a:undefined;
    function test() { … };
    }

  4. 预编译完成,执行代码:输出a,此时a的值为:undefined

  5. a赋值,此时GO对象内的a值变为100
    GO{
    a:100;
    function test() { … };
    }

  6. 执行函数test(),生成AO对象
    AO{

  7. }

  8. 将函数声明的变量添加进AO对象,值为undefined
    AO{
    a:undefined;
    }

  9. 函数没有传递参数,跳过函数预编译的第三步

  10. 函数里面没有声明函数,跳过函数预编译的第四步

  11. 执行函数,打印a,此时AO里面有属性a,则输出AO里面a的值,即输出: undefined

  12. AO的a赋值200,此时AO的a的值为200
    AO{
    a:200;
    }

  13. 输出a的值:200

  14. 将300的值赋值给b再赋值给a,此时b未声明,所以b为全局变量,将b添加进GO对象内,将a的值改为300
    GO{
    a:100;
    function test() { … };
    b:300;
    }
    AO{
    a:300;
    }

  15. 输出a的值:300,函数执行完成

  16. 输出b的值:300

  17. 输出a的值,此时a的值为GO里面的值:100

2.求输出结果

 //GO{//生成的GO对象//a:undefined;//test:function test(){ ... };//}function test() {console.log(b);//undefinedif (a) {//AO里面没有a的属性,自动寻找GO里面a的属性,此时a的值为undefined,语句不执行var b = 50;}console.log(b);//undefinedc = 100;//未声明则为全局变量,添加在GO对象内console.log(c); //100}var a;test();//执行函数预编译//AO{//生成的AO对象//b:undefined;//}a = 10;//GO里面的a赋值为10console.log(c);//100
function test() {return a;a = 1;function a() {var a = 2;}
}
console.log(test());
// AO: {//     a: function a() { },// }//ƒ a() {//        var a = 2;
//    }
function test() {a = 1;function a() { };var a = 2;return a;
}
console.log(test());
// AO: {//     a: undefined ->
//         a(){ } ->
//         1 ->
//         2,// }
a = 1;
function test(e) {function e() { }arguments[0] = 2; //与实参同步console.log(e); //2if (a) {var b = 3; // 这里也会变量提升,不要忘记}var c;a = 4;var a;console.log(b); //undefinedf = 5;console.log(c); // undefinedconsole.log(a); // 4
}
var a;
test(1);// GO: {//     a: undefined ->
//     1,
//     test: test(){ },
// }
// AO: {//     e: undefined ->
//         1 ->
//         e(){ } ->
//         2,
//     b: undefined,
//     c: undefined,
//     a: undefined ->
//         4,
// }

AO、GO实际上是为了解决作用域、作用域链相关所产生的一切问题

AO对象与GO对象——预编译(1)相关推荐

  1. 5单个编译总会编译全部_5分钟读懂JavaScript预编译

    大家都知道JavaScript是解释型语言,既然是解释型语言,就是编译一行,执行一行,那又何来预编译一说呢?脚本执行js引擎都做了什么呢?今天我们就来看看吧. 1-JavaScript运行三部曲 语法 ...

  2. JavaScript预编译过程

    JavaScript预编译过程 阶段(三个) 预编译过程 1. JavaScript代码执行之前的预编译 案例说明 2. 函数执行前的预编译 案例说明 总结 预编译两个小规则: 预编译前奏 阶段(三个 ...

  3. java函数ao活动对象_JS之预编译和执行顺序(全局和函数)

    预编译的两种情况 全局: 1.全局 直接是script标签中的代码,不包括函数执行 执行前: 1.首先生成一个GO(global object)对象,看不到,但是可以模拟出来用来分析 2.分析变量声明 ...

  4. js 预编译 AO对象跟GO对象

    注:GO对象会比AO对象先编译:预编译指在执行前会先预编译一次 GO对象 用于存放全局变量也称为全局作用域 <script>var name = '为空'var obg = {name:' ...

  5. C++封装常用对象和对头文件以及预编译机制的探索

    在C++实际开发中,难免会使用到一些你极为常用的算法(比如笔者经常使用的多线程技术),实现这些算法的类或是全局函数或是命名空间等等经常都要被使用多次,你会有哪些办法来使用呢?笔者有4个办法. 第一个方 ...

  6. PreparedStatement预编译的sql执行对象

    一.预编译,防sql注入 其中,设置参数值占位符索引从1开始:在由sql 连接对象创建 sql执行对象时候传入参数sql语句,在执行对象在执行方法时候就不用再传入sql语句: 数据库索引一般是从1开始 ...

  7. vs2015单元测试 - error LNK2011: 未链接预编译对象;映像可能不能运行

    单元测试的例子很多, 但都报这个错误 .obj : error LNK2011: 未链接预编译对象:映像可能不能运行 百度了很多篇文章都没有具体提到.Google一下找到答案 https://www. ...

  8. jdbc(跟着宝哥学java:jdbc) jdbc概念,铁打步骤,jdbc封装,预编译对象,sql攻击

    1 概念 jdbc:java database connection 通过java连接数据库 sun公司为java连接所有数据库提供的一组接口; jdbc驱动:各个数据库厂家为自己的数据库根据jdbc ...

  9. js预编译 GO 和AO

    一.前言 js的预编译,是js的基础内容,学好预编译,很多js开发问题都会迎刃而解. js在浏览器环境中运行流程一般分为三步走: 语法分析(检查代码的语法错误) 预编译(初始化变量和函数) 代码执行 ...

最新文章

  1. oracle配置oracle Database Configuration Assistant失败是什么原因?
  2. 关于外包团队的质量管理
  3. python多线程爬取图片
  4. OpenCASCADE:下载安装
  5. ASP.NET页面级别的事务
  6. maven 关联源码插件_繁琐的任务简单化,Maven的插件机制
  7. Ubuntu下用apache+perl搭建最简单的聊天室
  8. Python Tree库绘制多叉树的用法介绍
  9. Sobel两种算子形式
  10. 并联串联混合的电压和电流_电子电路基础,教你看懂电子电路,简单的串并联...
  11. 看看别人是如何进行大数据测试的?
  12. Medium之1468.计算税后工资
  13. UCSC下载ENCODE数据
  14. 在线万能文件格式转换器
  15. linux termios结构
  16. Python提取图片二维码Python
  17. python夯实基础日记-序列、列表、元组
  18. 万豪国际集团将开设南京W酒店;博格纳中国首家精品店开业;中国大陆第300家乐高专卖店开业|美通社头条...
  19. 秒表计时器怎么读_物理的秒表的读法怎么读???不是翻译!!
  20. 2022-2028全球及中国城市轨道交通信号系统行业研究深度分析报告

热门文章

  1. Science重磅 | 新技术Slide-seq能以高空间分辨率测量全基因组的表达情况
  2. 什么是计算机器语言?
  3. 6. ESP8266固件的下载
  4. 容器(Container)
  5. 【网络流24题】搭配飞行员(最大流+二分图匹配)
  6. 电视android已停止运行是什么意思,智能电视提示应用停止运行怎么办?当贝市场三招解决...
  7. java futuretask 单例_集群环境下java单例查询多了就异常
  8. 【数据存储】从hashMap、mysql、redis、到分布式
  9. SpringCloud Gateway 构建全局缓存 Request 解决 body 不可重复读问题
  10. FusionCharts Demo