JavaScript语言核心(二)--作用域链[[scope]] 及 执行对象 EC

  

  • 作用域是关于引擎如何寻找变量以及会在何处找到变量的规则
-词法作用域
 
    - 最重要特征是定义过程发生在代码书写截断
 
    - 作用域链基于代码的作用域嵌套而非调用栈
 
- 动态作用域是让作用域在代码运行过程中动态确定
 
    - 不关心函数和作用域如何声明以及何处声明
 
    - 只关心从何处调用
 
    - 作用域链基于调用栈而不是代码的作用域嵌套
 
- JS 并不具有动态作用域只有词法作用域 -> this机制某种程度上很像动态作用域

执行上下文EC (栈结构) 和 说明的环境 作用域链表 

  作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。在JavaScript中,变量的作用域有全局作用域和局部作用域两种。变量没有在函数内声明或者声明的时候没有带var就是全局变量,拥有全局作用域,window对象的所有属性拥有全局作用域;在代码任何地方都可以访问,函数内部声明并且以var修饰的变量就是局部变量,只能在函数体内使用,函数的参数虽然没有使用var但仍然是局部变量

  单纯的JavaScript作用域还是很好理解的,在一些类C编程语言中花括号内的每一段代码都有各自的作用域,而且变量在声明它们的代码段外是不可见的,称之为块级的作用域,JavaScript容易让初学者误会的地方也在于此,JavaScript并没有块级的作用域,只有函数级作用域:变量在声明它们的函数体及其子函数内是可见的。(较类C语言比较大的区别,允许嵌套的定义函数)。

 

JS权威指南中有一句很精辟的描述: ”JavaScript中的函数运行在它们被定义的作用域里,而不是它们被执行的作用域里.” 

  来分析下JS代码的执行流程,Js本身是单线程的,每当有function被执行时,就会产生一个新的上下文(execution context),这一上下文会被压入Js的上下文堆栈(context stack)中,function执行结束后则被弹出,因此Js解释器总是在栈顶上下文中执行。在生成新的上下文时,首先会绑定该上下文的变量对象(variable object,VO),其中包括arguments和该函数中定义的变量;之后会创建属于该上下文的作用域链(scope chain),最后将this赋予这一function所属的Object。

 

  函数也是对象,它有一个供JS引擎浏览的内部属性,叫[[Scope]]。该作用域是在函数定义时决定,而不是函数调用时决定。定义一个函数:不仅包含函数的代码逻辑,还必须引用当前的作用域链 Scope Chain

 

  作用域第一个对象始终是function所在环境的变量对象(VO),function a所在的环境是是在全局windows。

 

由于a是函数,所以会继续将,函数内定义的 局部变量 压入ScopeChain的顶端,此时局部变量的值没有只是声明,并没有初始化

 

函数调用:产生新的执行上下文,并将变量对象中的值,用来初始化Activation object中的属性。之后将 函数的ScopeChain 赋值给 Execution context的[[scope]]属性。运行过程中的符号就沿该ScopeChain来查找。

函数体内的变量,存储在函数定义时的作用域内。这种特性称为闭包。

for(var i = 0 ;i < elements.length;i++){

    (founction(n){

        elements[n].OnClick = founction(){

            elert(n);

        }

    })(i);

}  //output: 0,1,2,3,..

应当明白,注册的响应函数的作用域里,各自保存的单独一份n。

PS:Learning about what functions are and how scope works is the most important thing in Javascript.

posted @ 2015-11-19 13:57  yytiger  阅读(377)  评论(0编辑  收藏  举报