浅谈javascript函数执行过程

javascript函数执行过程:javascript

  1. 为函数建立一个执行环境前端

  2. 复制函数的 [[scopes]] 属性中的对象构建起执行环境的做用链域java

  3. 建立函数活动对象并推入执行环境做用链域的前端闭包

  4. 执行代码函数

  5. 销毁执行环境和活动对象(闭包状况下活动对象仍被引用没被销毁)this

 

用例子来讲明:spa

function Person(name) {
    this.getName = function() {
        return name;
    };

    this.setName = function(value) {
        name = value;
    };
}

var person = new Person("Candy");
alert(person.getName()); //"Candy"
person.setName("Greg");
alert(person.getName()); //"Greg"

 

以调用Person()构造函数、setName() 函数为例,函数执行过程当中,各对象的关系以下:对象

(1)未调用前,只存在全局变量对象blog

  全局变量中定义了Person() 构造函数,Person做为全局变量对象的一个属性,[[scopes]] 保存着Person() 构造函数的做用链域,由于Person() 构造函数是定义在全局变量对象里面的ip

  Person为何会有 [[scopes]] 属性???

  在建立函数时,会建立一个预先包含全局变量对象的做用链域,这个做用链域被保存在内部的 [[scopes]] 属性中

(2)new Person() 建立对象,调用以后,存在全局变量对象,Person对象

  用new调用构造函数会通过如下4个步骤:

    1. 建立一个新对象

    2. 将构造函数的做用域赋给新对象(所以this就指向这个新对象——person,这也是变量name为何不是对象属性的缘由)

    3. 执行构造函数中的代码(为新对象添加属性)

    4. 返回新对象

  重点说第3个过程,执行过程如图:

调用(执行)函数时,会为函数建立一个执行环境,而后经过复制函数的 [[scopes]] 属性中的对象构建起执行环境的做用链域。此后,又有一个活动对象(Person的活动对象)被建立并推入执行环境做用链域的前端,因此图中的做用链域有2层。

  调用完毕后,返回Person对象

Person执行环境在函数执行完毕后销毁,Person活动对象没有被销毁

  为何Person活动对象没有被销毁???

    这种状况属于闭包:Person活动对象仍然被getName、setName的 [[scopes]] 引用,即仍在做用链域中,因此没有被销毁

  注意:

    Person() 构造函数中定义了getName()、setName() 两个函数,还有函数的参数name

    new Person() 建立的 Person对象 的属性只有getName()、setName(),没有name属性,name不是用this声明的,不是Person对象的属性

     

(3)调用setName(),存在全局变量对象,Person对象

 

 建立setName() 的执行环境,而后经过复制函数的 [[scopes]] 属性中的对象构建起执行环境的做用链域。此后,又有一个活动对象(setName的活动对象)被建立并推入执行环境做用链域的前端,因此图中的做用链域有3层。

 函数执行完毕后:

 

 

setName执行环境和setName活动对象都被销毁,由于setName活动对象没有被引用

 

- 其余:

经过这个例子,也很好理解为何person.name是undefined,由于person对象没有name这个属性,getName、setName能访问name属性是由于它们经过做用链域访问到了Person活动对象中的name属性

 

PS:用构造函数建立的对象是独立的

相关文章
相关标签/搜索