要理解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. colpick-jQuery颜色选择器使用说明

      一.demo及下载网址:http://www.htmleaf.com/jQuery/Color-Picker/20141108417.html   二.使用效果   三.使用方法 1.引入js和c ...

  2. 状态压缩codeforces 11 D

    n个点m条边 m条边 求有几个环; #pragma comment(linker, "/STACK:102400000,102400000") #include <iostr ...

  3. win10 google浏览器设置

    在浏览器地址栏中输入命令: chrome://flags/ 撤销:chrome设置了禁止此页弹出提示框 chrome://settings/contentExceptions#popups

  4. SSM框架——详细整合教程(Spring+SpringMVC+MyBatis)【转载】

    最近在学习Spring+SpringMVC+MyBatis的整合.以下是参考网上的资料自己实践操作的详细步骤. 1.基本概念   1.1.Spring Spring是一个开源框架,Spring是于20 ...

  5. Python爬虫基础知识入门一

    一.什么是爬虫,爬虫能做什么 爬虫,即网络爬虫,大家可以理解为在网络上爬行的一直蜘蛛,互联网就比作一张大网,而爬虫便是在这张网上爬来爬去的蜘蛛咯,如果它遇到资源,那么它就会抓取下来.比如它在抓取一个网 ...

  6. [学习笔记]lca-倍增

    The article is to Jimmy.(方老师讲过了还不会,想怎样???) 求一棵树上两个节点的最近公共祖先有两种算法: (离线); 倍增(在线). 这篇博客只介绍倍增的写法. 表示节点的祖 ...

  7. ubuntu安装mysql--参考的网址

    Ubuntu服务器常用配置-mysql数据库的安装 - SegmentFault MySQL 社区-你身边最优秀的MySQL中文社区! MySQL咨询,MySQL培训,MySQL优化 - Powere ...

  8. 【随笔】mvc使用forms身份验证实现登陆

  9. bzoj3262: 陌上花开(树套树)

    #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #i ...

  10. D1

    第一天