JS----预编译(执行环境)

JavaScript 的执行环境
参考学习:https://blog.csdn.net/zwkkkk1/article/details/79766224#commentBox
JS执行顺序-函数声明提升、匿名函数、函数表达式
参考学习:https://www.cnblogs.com/can-i-do/p/8574450.html
JavaScript关于作用域、作用域链和闭包的理解:
参考学习:https://blog.csdn.net/whd526/article/details/70990994

声明的顺序是这样的:
1. 找到所有的函数声明,初始化函数体,如有同名的函数则会进行覆盖
2. 查找变量声明,初始化为undefined,如果已经存在同名的变量,就什么也不做直接略过

1.脚本执行js引擎都做了什么呢?

语法分析 很简单,就是引擎检查你的代码有没有什么低级的语法错误
预编译 简单理解就是在内存中开辟一些空间,存放一些变量与函数
解释执行 顾名思义便是执行代码

2.声明式函数 赋值型函数 匿名函数 自执行函数

   声明式函数 和 赋值型函数
        声明函数与赋值函数的区别在于: 在 JS 的预编译期间,声明式函数会被先提取出来,
        然后才按照顺序执行 JS代码。
    1 声明式:
            A(); // 'A ' function A() { console.log('A'); }
    2.赋值型:
            B(); // error, B is not a function var B = function() { console.log('B'); }   
    3.匿名函数       
                没有名字的函数就是匿名函数。        
            function() {} // 匿名函数   
    4.自执行函数
         (function() {
          console.log(3);
            })();

3.有关代码块script

代码块相互独立,变量和方法共享
代码块内出错依旧继续执行
JS引擎是按代码块顺序执行的(无法预处理)

4.函数

1.都是函数声明(后来居上)

f();  // 我是函数声明2
function f() {
  console.log('我是函数声明1');
}
function f() {
  console.log('我是函数声明2');
}  

2.函数声明提前于赋值函数

f();  // 我是函数声明
function f() {
  console.log('我是函数声明');
}
var f = function() {
  console.log('我是赋值型函数');
}

3.函数声明提升优先级大于 变量声明,函数声明覆盖 变量声明

console.log(f);  // Function
function f() {
  console.log(1);
}
var f = 3;

例题(声明式函数和赋值性函数):

var getName = function(){
  console.log(2);
}
function getName (){
  console.log(1);
}
getName();      //结果为2

=====================================

function getName (){
  console.log(1);
}
var getName = function(){
  console.log(2);
}
getName();  // 结果为2

=====================================

 getName();     //结果为 1
function getName() {
  console.log(1);
}
var getName = function() {
  console.log(2);
}

5.执行环境

执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为。每个执行环境都有一个与之关联的变量对象(variableobject,一般简写为VO),环境中定义的所有变量和函数都保存在这个对象中。虽然我们编写的代码无法访问这个对象,但解析器在处理数据时会在后台使用它。

6.预编译(函数执行前)

  1. 创建AO对象(Active Object)
  2. 查找函数形参及函数内变量声明,形参名及变量名作为AO对象的属性,值为undefined
  3. 实参形参相统一,实参值赋给形参
  4. 查找函数声明,函数名作为AO对象的属性,值为函数引用

7.预编译(脚本代码块script执行前)

  1. 查找全局变量声明(包括隐式全局变量声明,省略var声明),变量名作全局对象的属性,值为undefined
  2. 查找函数声明,函数名作为全局对象的属性,值为函数引用

8.变量对象 活动对象
参考学习:http://www.cnblogs.com/hezhi/p/10053025.html
https://www.qdfuns.com/article/13446/3510a52e53e9d43b1159f521a5832816.html
变量对象:每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中。
活动对象:在函数执行环境中,VO 是不能直接访问的,则将其活动对象(activation object)作为变量对象。

当一段 JavaScript 代码运行时,解释器(编译器)会创建执行环境,这里会有两个阶段:
    创建阶段(编译阶段,当函数被调用,但是开始执行函数内部代码之前)
        创建 Scope chain
        创建 VO / AO
        设置 this 的值
    代码执行阶段
        设置变量的值、
        函数的引用,
        然后解释、执行代码

对于创建 VO / AO,JavaScript 编译器主要做了下面的事:

根据函数的参数,创建并初始化 arguments对象
扫描函数内部代码,查找函数声明(Function declaration)
    对于所有找到的函数声明,将函数名和函数引用存入 VO / AO 中
    如果 VO / AO 中已经有同名的函数(变量),那么就进行覆盖
扫描函数内部代码,查找变量声明(Variable declaration)
    对于所有找到的变量声明,将变量名存入VO/AO中,并初始化为"undefined"
    如果变量名称跟已经声明的形参或函数相同,则变量声明不会干扰已经存在的这类属性

=====================================
全局变量对象

  var foo = 10;
    function bar() {} // // 函数声明
    (function baz() {}); // 函数表达式

console.log(
  this.foo == foo, // true
  window.bar == bar // true
);

console.log(baz); // 引用错误,baz没有被定义

全局上下文中的变量对象(VO)会有如下属性:

在这里插入图片描述全局变量对象

活动对象:

function foo(x, y) {
  var z = 30;
  function bar() {} // 函数声明
  (function baz() {}); // 函数表达式
}
foo(10, 20);

“foo”函数上下文的下一个激活对象(AO)如下图所示:
在这里插入图片描述活动对象

posted @ 2019-05-15 18:20  princeness  阅读(262)  评论(0编辑  收藏  举报