手记

初识JavaScript的解析与执行过程

JavaScript的解析与执行过程

1. 全局预处理——先扫描函数声明,再扫描变量声明;

  • 函数:用声明的方式创建的函数;
  • 变量:用var定义的变量;初始化为undefined;

如果出现命名冲突 时:

  • 函数声明:覆盖;
  • 变量声明:忽略;

例如:

<script>
f(); //fff
g(); //TypeError: g is not a function
function f() {
  console.log('fff');
}
var g = function () {
  console.log('ggg');
}
</script>
f()函数是声明方式创建的函数,g()是函数表达式,全局预处理时词法环境中,只能是用声明的方式创建的函数。

因此,全局预处理时g()从语义上看,应该是函数,但是由于g()是函数表达式,不会在词法环境中,所以调用时会报错。

例如:


console.log(a); // undefined
console.log(b); //ReferenceError: b is not defined
var a = 1;
b = 2;
同理,词法环境中只有用var定义的变量。

例如:


alert(f);             //function f(){alert('567');}
var f = 1;
function f() {
    alert('123');
}
var f = 2;
function f() {
    alert('567');
}
var f = function() {
    alert('890');
}
命名冲突时,函数具有“优先权”,变量会直接被忽略,而函数会被覆盖。

2. 全局执行过程

例如:


alert(a);       //undefined
alert(b);       //ReferenceError: b is not defined
alert(f);        //function f() {console.log('f');}
alert(g);       //undefined
var a = 1;
b = 2;
alert(b);          //2
function f() {
  console.log('f');
}
var g = function () {
  console.log('g');
}
alert(g);           //function () {console.log('g');}
为了分析方便我们可以使用词法环境:

LexicalEnvironment {} === window;

全局预处理时:


window {
    //先扫描函数声明:
    f: 指向函数,
    //再扫面变量声明:
    a: undefined,
    g: undefined
}

全局执行时:


window {
    f: 指向函数,
    a: 1,
    b: 2,
    g: 指向函数
}

3. 函数预处理阶段

  • 每调用一次,产生一个词法环境(或执行上下文Execution Context);
  • 先传入函数的参数,若参数值为空,初始化undefined;
  • 然后是内部函数声明,若发生命名冲突,会覆盖;
  • 接着就是内部var变量声明,若发生命名冲突,会忽略;

4. 函数执行阶段

  • 给预处理阶段的成员赋值;

  • 无var声明的变量,会成为全局成员;

例如:


function f(a, b) {
  alert(a);            //1
  alert(b);            //funciton b(){} 
  var a = 100;
  function b() {
  }
}
f(1, 2);

VO(Variable Object)——>变量对象

函数中的激活对象:
VO(functionContext)=== AO;

代码中:


AO(f) {
    a: 1,                   //变量命名冲突,忽略
    b: 指向函数,            //函数命名冲突,覆盖
}

例如:


function test(a, b) {
  alert(a);     //10
  alert(b);     //undefined
  alert(c);     //undefined
  alert(d);     //function d(){}
  alert(e);     //undefined
//alert(x);     //ReferenceError: x is not defined
  var c = 10;
  alert(c);     //10
  function d() {
  }
  var e = function _e() {
  };
  alert(e);     //function _e(){}
  (function x() {
  });
  b = 20;
  alert(b);     //20
}
test(10)

函数预处理时:


AO(test) {

    //参数:
    a: 10,
    b: undefined,

    //函数声明:
    d: 指向函数,

    //变量声明:
    c: undefined,
    e: undefined
}

函数执行时:


AO(test) {

    a: 10,
    b: 20,
    d: 指向函数,
    c: 10,
    e: 指向函数
}

45人推荐
随时随地看视频
慕课网APP

热门评论

“命名冲突时,函数具有“优先权”,变量会直接被忽略,而函数会被覆盖。”

这个说法不对吧,理解了变量声明提升就很好理解了。如果把代码改一下,把alert放最后

var f = 1; 

function f() {

 alert('123'); 

var f = 2; 

function f() {

 alert('567'); 

var f = function() {

 alert('890'); 

}

alert(f); 

最后输出是

function() {

 alert('890'); 

}

和是否变量、函数并没有关系

帮助挺大,本人对函数作用域跟闭包比较感兴趣,然而现在在外面没工具敲代码,后面看起来有点费劲,因为后面很多都是引用前面声明的,要看懂作者要表达的意思要翻上去几遍…

查看全部评论