要理解javascript函数的定义与执行,首先需要知道这几个重要的概念,现在可以先知道稍后再理解!

函数的执行环境(excution context)、活动对象(call object)、作用域(scope)、作用域链(scope chain)。
 
接下来,我们以这个函数为例进行分析:
 
 
步骤:
1、设置作用域链
当定义函数a的时候,JS解释器会将函数a的作用域链(scope chain)设置为“定义a时a所在的环境”,此处a第一个添加的作用域是window对象。(如果a是一个全局函数,则scope chain中只有window对象。)
个人见解:作用域链里面其实是包含的活动对象,活动对象可以理解为是用来识别作用域的。(就像是一个商场分为A、B、C  三个区,就可以理解为在这个商场的作用域链里面,有A、B、C 3个活动对象,3个范围!(“个人见解,可能不恰当”)。
2、执行环境
当执行函数a的时候,a会进入相应的执行环境(excution context)。
个人见解:创建执行环境分为创建作用域创建活动对象两步。
3、作用域
当创建执行环境的过程中,首先会为a 添加一个scope属性,即a的作用域,其值就是第一步中的scope chain。即a.scope = a的作用域链。
个人见解:可以把作用域和作用域链理解成是名字不同但作用相同!
4、创建活动对象
创建完作用域,紧接着执行环境会创建一个活动对象(call object)。活动对象也是一个拥有属性的对象,但它不具有原型而且不能通过javascript代码直接访问(可以看下面的图或者个人见解理解)。创建完活动对象后,把活动对象添加到a的作用域链的最顶端。此时a的作用域链包含两个对象:a的活动对象和window对象。
下一步是在活动对象上添加一个arguments属性,它保存着调用函数a时所传递的参数。
最后所有的函数a的形参和内部的函数b的引用也被添加到a的活动对象上。在这一步中,完成了函数b的定义,因此如同第3步,函数b的作用域被设置为b所定义的环境,即a的作用域。(就类似于a的作用域链中第一个加入的作用域是window对象。)!
个人见解:(1) 活动对象是一个为了理解而添加的名词,实际不存在,所以不具有原型、也不能用实际代码访问。(类似于磁感线,只是为了描述)
 
完结:到此,整个函数a从定义到执行的步骤就完成了。此时a返回b的引用给c,又因为函数b的作用域链包含了函数a的活动对象的引用,也就是说b中可以访问到a中定义的所有变量和函数。又函数b被c引用,函数b依赖于a,因此函数a再返回后不会被GC回收(参考最下方javascript的垃圾回收机制)!
 
当函数b被执行的时候也会像以上步骤一样。因此执行时b的作用域链包含了3个对象:b的活动对象,a的活动对象,window对象,如图所示:
 
如图所示,当在函数b访问一个变量的时候,搜索顺序是:
b的活动对象 —>b的原型对象(存在的话)—>a的活动对象 —>window对象
变量查找机制:先查找自身的活动对象,如果存在则返回,如果不存在且该函数存在prototype原型对象,则查找原型对象。依次查找a的活动对象、window对象。直到找到为止,如果整个作用域链上没有找到,则返回undefined。
 
总结:以上提到了两个重要的词语:函数的定义与执行。文中提到函数的作用域是在定义函数的时候就已经确定,而不是在执行的时候确定(参看步骤1和3).用一段代码来说明这个问题:
 function f(x){
var g = function(){ return x;}
return g;
}
var h = f(1);
alert(h());
这段代码中变量h指向了f中的那个匿名函数(由g返回,也可以理解为不匿名,因为有名字g(不正规理解))。
(1)h的作用域在定义的时候确定:
个人理解h的作用域链:g的活动对象->f的活动对象->window对象(因为此处h代表的是返回的"g()"函数,既然是定义为准,就应该是定义"g()"函数时确定,所以 h.scope chain = g.scope chain )
网上参考h的作用域链:h的活动对象 ->f的活动对象->window对象
(2)h的作用域在执行(alert( h ( ) )的时候确定:
h的作用域链:h的活动对象->alert的活动对象->window对象。
 结果:(1)应该输出1 (2)应该输出undefined  。
实践证明函数的作用域是在定义这个函数的时候就已经确定了!
 

补充:Javascript的垃圾回收机制

在Javascript中,如果一个对象不再被引用,那么这个对象就会被GC回收。如果两个对象互相引用,而不再被第3者所引用,那么这两个互相引用的对象也会被回收。因为函数a被b引用,b又被a外的c引用,这就是为什么函数a执行后不会被回收的原因。

function a(){

var i = 0;

var b = function(){ alert(++i);}

return b;

}

var c = a();

c();

以上代码如果没有return b; 当函数a执行完后就会被回收!b引用a,而b不再被第3者c所引用(没有返回数据给c),那么这两个互相引用的对象也会被回收。

 
参考文档:http://www.jb51.net/article/24101.htm  (javascript深入理解js闭包)

javascript函数的定义与执行的更多相关文章

  1. Javascript函数(定义、传值、重载)

    Javascript 函数的定义的方式有不止一种. 第一种方式: function fn1(){ alert(typeof fn1); alert(“fn1”); } 在调用的时候直接就可以fu1() ...

  2. JavaScript 函数的定义-调用、注意事项

    函数定义 函数语句定义 function(a,b){ return a+b; } 表达式定义 var add = function(a,b){return a+b}; //函数表达式可以包含名称,这在 ...

  3. JavaScript 函数全局变量定义

    在 JavaScript 中, 作用域 影响着变量的作用范围.在函数外定义的变量具有 全局 作用域.这意味着,具有全局作用域的变量可以在代码的任何地方被调用. 没有使用var关键字定义的变量,会被自动 ...

  4. javascript函数 (二 定义函数的三种方法)

    javascript定义函数(声明函数)可以有三种方法:正常方法.构造函数.函数直接量 <html><head></head><body> <sc ...

  5. 6 JavaScript函数&内置构造&函数提升&函数对象&箭头函数&函数参数&参数的值传递与对象传递

    JavaScript函数:使用关键字function定义,也可以使用内置的JavaScript函数构造器定义 匿名函数: 函数表达式可以存储在变量中,并且该变量也可以作为函数使用. 实际上是匿名函数. ...

  6. 在JavaScript函数中使用EL表达式注意的事项

    最近在使用JSP显示从Servlet带过来的数据时,大量的使用到了EL表达式,并且有些EL表达式是在使用到JavaScript的函数时作为参数传入的,举个例子,比如下面的样子: 这个HTML标签的意思 ...

  7. JS:javascript 函数后面有多个小括号是怎么回事?f( )( )( )...

    有时我们看见js函数后面跟着多个小括号是怎么回事?f( )( )( )... f()意思是执行f函数,返回子函数 f()()执行子函数,返回孙函数 f()()()执行孙函数 ()()表示定义并执行,使 ...

  8. JavaScript函数、对象和数组

    一.JavaScript函数 1.定义函数:函数的通用语法如下 function function_name([parameter [, ...]]) { statements; } 由关键字func ...

  9. 深入理解javascript函数定义与函数作用域

    最近在学习javascript的函数,函数是javascript的一等对象,想要学好javascript,就必须深刻理解函数.本人把思路整理成文章,一是为了加深自己函数的理解,二是给读者提供学习的途径 ...

随机推荐

  1. 【BZOJ 2599】【IOI 2011】Race 点分治

    裸的点分治,然而我因为循环赋值$s$时把$i <= k$写成$i <= n$了,WA了好长时间 #include<cstdio> #include<cstring> ...

  2. Jetty应用服务器的安装详解

    Jetty是一个开源的Servlet容器和应用服务器,它极度轻量级.高便携性.功能强大.灵活和扩展性好,而且支持各种技术如SPDY.WebSocket.OSGi.JMX.JNDI和JAAS.Jetty ...

  3. poj1182 带权并查集

    食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 60225   Accepted: 17656 Description ...

  4. python 学习笔记11(objgraph)

    33. objgraph objgraph是Python的一个第三方包.安装之前需要安装xdot. 用途 安装 例子

  5. BZOJ 1112: [POI2008]砖块Klo

    1112: [POI2008]砖块Klo Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1736  Solved: 606[Submit][Statu ...

  6. 【BZOJ-3956】Count ST表 + 单调栈

    3956: Count Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 173  Solved: 99[Submit][Status][Discuss] ...

  7. codevs1138 聪明的质监员

    题目描述 Description 小 T 是一名质量监督员,最近负责检验一批矿产的质量.这批矿产共有n 个矿石,从1到n 逐一编号,每个矿石都有自己的重量wi 以及价值vi.检验矿产的流程是:见图   ...

  8. hdu 4609 FFT

    题意:给出一堆数,问从这些数中取3个能组成三角形的概率? sol:其实就是问从这些数里取3个组成三角形有多少种取法 脑洞大开的解法:用FFT 设一开始的数是1 3 3 4 作一个向量x,其中x[i]= ...

  9. poj3502 恶心题

    巨恶心的一个题::>_<:: 题意:给出航班航线和大陆,找航线上距离大陆最远的某一点距离大陆边缘的距离 标准算法:二分答案,从大陆边界向外扩展,扩展出来的面积会覆盖航线.找出航线上最后被覆 ...

  10. Allegro笔记三

    1.设置Gerber导出目录 可以在$Install_Dir/share/pcb/text/env.txt目录里面添加:“set artpath = . ../Gerber/”语句. 其他各种文件夹设 ...