1函数的创建和调用都发生了什么?
1.1函数的创建
1.1.1执行环境
执行环境定义了变量或函数有权访问其他的数据。
1.1.2变量对象
每个执行环境都有一个与之关联的变量对象,通过作用域链来关联,这个变量对象中保存着执行环境中定义的所有变量和函数。我们编写的代码是无法访问到的,但解析器在处理数据时会在后台使用它。 ------- 关于执行环境和变量对象的关系可见下面的图片
1.1.3作用域链:
作用域链的前端,始终都是当前执行的代码所在环境的变量对象。如果这个环境是函数,则将其活动对象作为变量对象。活动对象最初只包含一个变量,即函数内部的arguments对象。作用域链的下一个变量对象来自包含环境,而再下一个变量对象则来自下一个包含环境。这样,一直延续到全局执行环境;全局执行环境的变量对象始终都是作用域链中的最后一个对象。
创建一个函数compare,
function compare(value1,value2){ if(value1<value2){ return -1;} else if(value1>value2){ return 1; }else{ return 0; } } var result=compare(5,10);
首先会创建一个包含全局变量对象的作用域链,这个作用域链被保存在函数内部的[[Scope]]属性中
1.2函数调用时
会为函数compare创建一个执行环境,及相应的作用域链0(通过复制函数的[[Scope]]属性中的对象构建起执行环境的作用域链,此后,又有一个活动对象(变量对象)被创建并被推入执行环境作用域链前端)。然后使用arguments和value1,value2来初始化函数的活动对象。
如下面为一个compare函数的执行环境和作用域链,变量对象之间的关系
就compare函数而言,它包含2个变量对象,一个全局变量对象和一个本地活动对象。
1.3查找变量
在函数执行过程中,为读取和写入变量的值,需要在作用域链中查找变量。这里就需要涉及到标识符查找。首先在作用域链的前端开始查找匹配的标识符,如果在局部环境中找到了标识符,搜索过程就停止,变量就绪。如果没找到,则继续沿着作用域链向上搜索。搜索过程一直追溯到全局环境的变量对象。如果在全局环境中野没有找到标识符,则意味着变量未声明。返报错,ReferenceError: 变量is not defined,
1.4函数执行完毕
一般来讲,当函数执行完毕后,局部活动对象就会被销毁,内存中仅保存全局作用域(直至浏览器关闭时才销毁)。但是闭包会保留对函数的作用域的引用。
2.作用域链的本质
是一个指向变量对象的指针列表,它只引用但不包含实际的变量对象。
3.作用域链的作用
保证对当前执行环境有权访问的变量或函数的有序访问
4延长作用域链
通过在作用域链的前端临时增加一个变量对象,该变量对象会在代码执行以后被移除
4.2try-catch语句的catch块
会创建一个新的变量对象,其中包含的是被抛出的错误对象的声明
4.3with语句
会将制定的对象添加到作用域链中