`
安静思考
  • 浏览: 12639 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

JavaScript中函数的范围链

    博客分类:
  • JS
阅读更多

1、函数介绍

    函数在JavaScript中能够通过单一的调用而执行一组操作。在JavaScript中,函数(function)有几种不同的称谓,分别是:函数、方法和构造器,定义一个函数为某一个对象的属性,则称这个函数为方法,构造器则是函数与new操作符一起操作的函数。有以下几种定义函数的方式:

  •     函数 声明
function maximum(x,y){
    if(x > y)
        return x;
    else
        return y;
}
maximum(5,6) //Returns 6;

这种定义的方式在定义顶层函数时非常常用。

  •     function literals

 

var obj = new Object();
obj.maximum = function (x,y) {
                if(x > y)
                    return x;
                else
                    return y;
              };
obj.maximum(5,6) //Returns 6;

 这种定义方式在定义函数作为一个对象的方法时最常用。

  •     构造函数

 

var maximum = new Function ("x","y","if(x > y) return x; else return y;");

maximum(5,6);  //Returns 6;

  这种定义方式不常用。

2、函数定义

    函数定义指的是:在JavaScript引擎内定义一个函数对象。对于一个顶层函数,会把这个对象作为一个属性增加到全局对象中;对于一个内嵌的函数(定义在函数内的函数),则会把这个对象加到激活对象 (activation object) 中。顶层函数会在执行这个脚本之前定义,也就是说,在执行脚本之前,会为这个顶层函数创建函数对象,并加入到全局对象中。看下面的例子,一旦JavaScript解释器解析完毕开始执行下面的语句时,会为‘func’创建函数对象并作为一个属性加入到全局对象中:

/*函数'func'在这里可以被调用,因为func的定义在脚本开始执行时已经发生.*/
alert(func(2));  //Returns 8
//这个语句覆盖了func的值为true.
var func = true;
alert(func);     //prints true;
/*当脚本开始执行的时候,解析下面的语句并且会为函数‘func’定义函数对象。*/
function func(x){
      return x * x * x;
}

 而对于一个内嵌的函数,则函数定义过程发生在当调用外部函数的时候,会定义内嵌的函数,并为这个内嵌函数创建函数对象,加入到外部函数的激活对象(activation object)中。例如:

function outerFn()

{

    function innerFn()

    {

   

    }

}

 

outerFn(); //调用 outerFn 会引起innerFn的定义当outerFn 函数体开始执行的时候

 注意 :对于函数构造器来说,函数定义会发生在调用‘Function’构造器的时间。

3、范围链

    范围链指的是一个对象链,当在对象链中查找一个变量的时候,对象链的对象的属性能够被查找在JavaScript中,函数在定义之后就会有他们的范围链,这个范围链是在他们执行的时候的范围链,而不是在他们调用的时候的范围链 It is this scope chain in which they execute rather than the scope chain from which they are invoked. ,比如:

function outerFn(i){
    return function innerFn(){
        return i;
    }
}
var innerFn = outerFn(4);
innerFn();//Returns 4
 

 在掉用innerFn的时候,变量i并没有在innerFn内部定义,也没有在全局对象中定义,但是这句话是可以执行的,返回值为4,那么这个i是从哪来的呢?下面从顶层函数来慢慢分析:

3.1 全局函数

    顶层函数的执行范围链是非常直接的:

var x = 10;

var y = 0;

function testFn(i){

    var x = true;

    y = y + 1;

    alert(i);

}

testFn(10);

 Figure 1:全局函数的范围链

  • Global Object:在JavaScript引擎开始执行代码的时候,会创建一个全局对象,并初始化全局对象一些预定义的值,像 ‘Infinity’, ‘Math’等。脚本中的全局变量只是定义在这个全局对象中的属性,像上面代码中的x呵y变量。
  • Activation Object:当JavaScript引擎调用任何的函数的时候,它会创建一个新的对象,也就是Activation Object激活对象,然后将在函数内部定义的变量以及通过arguments传递进来的参数都会被定义到这个激活对象中。然后将这个对象加入到执行范围链的前端。

 3.2 内嵌函数

    对于内嵌函数,范围链的形成比较复杂,看下面的例子:

function outerFn(i,j)

{

    var x = i + j;

    return function innerFn(x)

    {

        return i + x;

    }

}

 

var func1 = outerFn(5,6);

var func2 = outerFn(10,20);

 

alert(func1(10));//Returns 15

alert(func2(10));//Returns 20

 能够看到,在分别调用func1(10)和func2(10)的时候,变量i具有不同的值,下面一步步分析:

    在下面的语句执行的时候

var func1 = outerFn(5,6);

 会发生三个个动作,一是创建outerFn函数的激活对象(Activation Object);然后定义innerFn函数,并且作为outerFn的激活对象的一个属性加入到 outerFn的激活对象中;因为每个函数在定义的时候都会有它自己的范围链,并且这个范围链是执行范围链,这个时候的执行范围链包含outerFn的激活对象以及全局对象。然后会把这个执行范围链为内嵌函数innerFn保存起来。执行完毕后,返回内嵌对象,并用func1来引用。

    当执行这条语句时:

   

alert(func1(10));//Returns 15

     创建func1的激活对象,并且加入到已经保存的执行范围链的最前端,就是在这个执行范围链下,func1开始执行。这样在这个范围链下,i属性就解决了。看下图,能表现的更清楚,对于func1的调用时候的范围链,如图所示:

对于func2的执行范围链,看下图:

 

从这两个图就能很清晰的看出来在func1呵func2两个方法调用的时候,i的值是不一样的。

4 激活对象与范围链

    是不是在函数调用的时候,创建这个函数的激活对象,然后在函数执行完毕之后,这个激活对象就会被销毁呢?为了解答这个问题,下面根据例子来说明一下激活对象与范围链的关系。

    4.1 没有内嵌函数的情况

    看下面的例子:

 

function outerFn(x){

   return x*x;

}

var y = outerFn(2);

 没有内嵌函数,在调用函数时,会创建这个函数的激活对象,并把这个激活对象加入到执行范围链的最前端,需要注意的是,范围链是 唯一持有 这个激活对象的对象。当函数执行完毕之后,就把这个激活对象从执行范围链中删除,由于没有别的对象再引用这个激活对象了,因此这个激活对象会被垃圾回收器回收。

    4.2 有内嵌函数,但是内嵌函数没有被其包围函数之外的对象引用

   

function outerFn(x)

{

    //No reference for 'square' outside 'outerFn'

    function square(x)

    {

        return x*x;

    }

     

    //No reference for 'cube' outside 'outerFn'

    function cube(x)

    {

        return x*x*x;

    }

    var temp = square(x);

    return temp/2;

}

var y = outerFn(5);

    在一个函数有内嵌函数,并且内嵌函数没有被其外围函数之外的对象引用的时候,当调用外围函数时,这个函数的激活对象被创建,并将其加入到执行范围链的最前端,并且同样会被起内嵌函数的已保存范围链引用(在外围函数调用时,内嵌函数开始定义,内嵌函数定义的时候,会为其创建范围链),当这个外围函数退出的时候,它的激活对象从执行范围链中被删除。由于外围函数的激活对象和其内嵌对象是相互引用的,并且这两个对象都没有被外部的对象所引用,因此会被垃圾回收器回收。

4.3 内嵌函数被包围函数的外部对象引用

// 例子1
function outerFn(x)                            

{

    //Inner function referenced outside through return

   //value of 'outerFn'

       return function innerFn()

       {

           return x*x;

       }

   }

 

   //Reference to inner function returned.

   var square = outerFn(5);

square();
例子2
var square;

function outerFn(x)

{

//Inner function referenced outside through global variable

//'square'

    square = function innerFn()

    {

        return x*x;

    }

}

 

outerFn(5);

square();
 

 在具有内嵌函数,并且内嵌函数被外围对象引用的时候,当执行这个外部函数时,这个外部函数的激活对象被创建,并且把激活对象加入到执行范围链的最前端,同时,这个对象被内嵌函数的已保存的范围链所引用(在内嵌函数定义的时候会保存一个范围链)。当外部函数退出,这个激活对象会从执行范围链中被删除,但是它仍然在内嵌函数保存的范围链中有一个引用。由于有个外部的引用指向内嵌函数,因此这个激活对象一直保存在内嵌函数的已保存范围链中,并且在内嵌函数执行的时候可以被访问。

5 闭包和循环引用

    这里讲一下由于闭包而引起的循环引用内存泄漏。闭包通常指的是内嵌的函数可以在其包围函数的外部调用,下面给出一个小例子:

function outerFn(x)

{

    x.func = function innerFn()

             {

             }

}

 

var div = document.createElement("DIV");

outerFn(div);

 通过这个例子我们能够观察到在DOM对象和JS对象之间的循环引用被创建。DOM对象div通过func属性指向内嵌的函数innerFn,而 内嵌的函数innerFn也有一个指向DOM对象div的引用x,这个x是保存在outerFn的激活对象中,并且这个激活对象被保存到内嵌函数的已保存范围链中。

 

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

注意 :这篇文章翻译自MSDN的一篇文章,自己做了些加工与说明。可以点击这里 查看原文

  • 大小: 14.1 KB
  • 大小: 37.9 KB
  • 大小: 38.6 KB
分享到:
评论

相关推荐

    Python课程设计 课设 手写数字识别卷积神经网络源码+文档说明.zip

    高分设计源码,详情请查看资源内容中使用说明 高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明

    SpringBoot2.0快速开发框架权限.rar

    SpringBoot2.0快速开发框架权限.rarSpringBoot2.0快速开发框架权限.rarSpringBoot2.0快速开发框架权限.rar

    大语言模型的微调和推理baichuan7B, chatglm2-6B, Qwen-7B-chat源码.zip

    详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;

    基于Qt与STM32平台开发的汽车车机系统上位机

    基于Qt开发的汽车车机系统上位机 & 常见类型汽车传感器信号模拟发生器 任务和要求: 任务: 根据发动机测控系统信号需求,设计一套发动机信号模拟器人机交互系统,能够根据需要向下位机输出控制信号,使其输出发动机测控系统需要的传感器模拟信号,给发动机测控系统的开发提供方便。 要求: 1.设计应包含上位机与下位机的交互程序及人机交互界面的设计,与下位机设计相结合,使其能够实现全部类型发动机传感器信号的模拟输出及显示。 2.设计中需要采用模块化开发程序。 3.所设计的人机交互界面简洁合理。 4.应考虑所设计系统的实用性。 具体工作内容: 1.根据设计目标,查阅相关设计标准和设计方法资料,对发动机信号模拟器设计中的关键工程原理和工程方法进行提炼,并围绕关键问题进行国内外设计现状调研,开展分析、评价与总结,确定主要研究内容,制定设计技术路线,制定设计计划(周进度),撰写开题报告,并进行开题答辩,开题报告参考文献应不少于15篇(其中外文文献不少于 4 篇,近五年文献不少于三分之一)。 2.根据设计要求和技术指标,进行满足功能原理需求的多方案拟定,考虑安全、 标准等多因素进行技术性与经济性评价

    实验-三、数据库安全性(目的、要求和模板).doc

    实验-三、数据库安全性(目的、要求和模板).doc

    毕设绝技 - 4天玩乐完成商城系统完整资料day02

    文件为第二天视频教程 在毕业设计的挑战中,有时我们需要以极短的时间完成一个相对复杂的项目,比如一个商城系统。虽然时间紧迫,但只要我们合理规划、高效执行,完全有可能在4天内完成一个基础且功能完备的商城系统。 商城系统,也被称为网上商城系统或Online Mall system,是一种功能完善的网上销售系统。该系统主要包括产品发布、在线订购、在线支付、在线客服等功能模块,旨在为企业或个人提供一个在线销售平台,实现商品的展示、交易和客户服务。 商城系统具有多种核心功能,如商品管理、订单管理、用户管理和营销管理。商品管理功能支持商品的添加、编辑、删除、分类和搜索,满足商家对商品信息的全面管理需求。订单管理功能则涵盖订单的生成、支付、发货、退款和评价等环节,确保交易流程的顺畅进行。用户管理功能包括用户的注册、登录、个人信息管理和收货地址管理等,提升用户体验。而营销管理功能则通过促销活动的设置、优惠券的发放和积分兑换等手段,帮助商家提升销售业绩。 商城系统的特点主要体现在功能性、易用性和安全性上。商城系统注重功能性的开发,每个功能都有其发挥作用的地方,满足商家的实际需求。

    忻州师范学院-论文答辩PPT模板我给母校送模板作品.pptx

    PPT模板,答辩PPT模板,毕业答辩,学术汇报,母校模板,我给母校送模板作品,周会汇报,开题答辩,教育主题模板下载。PPT素材下载。

    小型餐饮管理系统-数据库设计报告.doc

    小型餐饮管理系统-数据库设计报告.doc

    毕业设计+Python+基于OpenCV的交通路口红绿灯控制系统设计+Sqlite +PyCharm 1.zip.zip

    本资源中的源码都是经过本地编译过可运行的,下载后按照文档配置好环境就可以运行。资源项目的难度比较适中,内容都是经过助教老师审定过的,应该能够满足学习、使用需求,如果有需要的话可以放心下载使用。有任何问题也可以随时私信博主,博主会第一时间给您解答!!! 本资源中的源码都是经过本地编译过可运行的,下载后按照文档配置好环境就可以运行。资源项目的难度比较适中,内容都是经过助教老师审定过的,应该能够满足学习、使用需求,如果有需要的话可以放心下载使用。有任何问题也可以随时私信博主,博主会第一时间给您解答!!! 本资源中的源码都是经过本地编译过可运行的,下载后按照文档配置好环境就可以运行。资源项目的难度比较适中,内容都是经过助教老师审定过的,应该能够满足学习、使用需求,如果有需要的话可以放心下载使用。有任何问题也可以随时私信博主,博主会第一时间给您解答!!

    西南交通大学-毕业答辩PPT模板我给母校送模板作品.pptx

    PPT模板,答辩PPT模板,毕业答辩,学术汇报,母校模板,我给母校送模板作品,周会汇报,开题答辩,教育主题模板下载。PPT素材下载。

    2024年中国中空纤维膜行业研究报告.docx

    2024年中国中空纤维膜行业研究报告

    四川师范大学-PPT模板我给母校送模板作品.pptx

    PPT模板,答辩PPT模板,毕业答辩,学术汇报,母校模板,我给母校送模板作品,周会汇报,开题答辩,教育主题模板下载。PPT素材下载。

    实验三、数据库安全性实验报告.doc

    实验三、数据库安全性实验报告.doc

    西北农林科技大学-PPT模板我给母校送模板作品.pptx

    PPT模板,答辩PPT模板,毕业答辩,学术汇报,母校模板,我给母校送模板作品,周会汇报,开题答辩,教育主题模板下载。PPT素材下载。

    java电子相册源码.rar

    java电子相册源码.rarjava电子相册源码.rarjava电子相册源码.rarjava电子相册源码.rar

    玉米脱粒机设计及其总装配图(论文、dwg图).rar

    玉米脱粒机设计及其总装配图(论文、dwg图)

    studyopencv2

    studyopencv2

    2024-2030全球与中国牛肉卷饼市场现状及未来发展趋势.docx

    2024-2030全球与中国牛肉卷饼市场现状及未来发展趋势

    在KITTI车辆数据集,采用随机多尺度变化增强车辆训练集样本数量,采用k-means聚类获取最优先验候选框大小

    在KITTI车辆数据集,采用随机多尺度变化增强车辆训练集样本数量,采用k-means聚类获取最优先验候选框大小,引入到YOLOv3模型中,提升模型的车辆检测精度和鲁棒性。.zip

    基于Vue+SSM高校疫情信息管理系统源码.zip

    详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;

Global site tag (gtag.js) - Google Analytics