手机版

JavaScript范围链示例的详细说明

时间:2021-08-27 来源:互联网 编辑:宝哥软件园 浏览:

本文的例子讲述了JavaScript范围链。分享给大家参考,如下:

和其他语言一样,变量和函数的范围揭示了这些变量和函数的搜索路径。对于JavaScript来说,理解作用域更重要,因为在JavaScript中,作用域可以用来确定这个的值,而JavaScript有一个闭包,可以访问外部环境的作用域。每个JavaScript函数都是一个Function对象的实例,它有一个内部属性[[Scope]],只能由JavaScript引擎访问。通过[[作用域]]属性,可以访问函数的作用域链,这样可以搜索变量和函数,判断变量和函数位于作用域链中的哪个活动对象。

简单范围链

创建函数时,因为函数是函数对象的实例,所以它还具有内部属性[[作用域]],该属性指向作用域链,默认情况下,作用域链至少包含一个全局对象变量。

函数比较(值1,值2){ if(值1值2){ return-1;} else if(value 1 value 2){ return 1;} else { return 0;}}var结果=compare(5,10);上面的代码首先定义了一个compare()函数,然后在全局范围内调用这个函数。创建compare()函数时,函数的作用域链如下图所示:

当在全局范围内调用并执行compare()函数时,JavaScript引擎将创建一个执行上下文的内部对象,该对象定义了执行函数的环境。函数的运行时上下文在执行时是不同的,所以多次调用会导致多个运行时上下文的创建和销毁。

每个运行时上下文都有自己的范围链,用于解析变量和函数的标识符。

运行时上下文在函数调用执行时创建,在函数执行时销毁。创建运行时上下文时,将首先复制被调用函数的[[Scope]]属性中的对象,然后创建一个活动对象(用作变量对象),并将其推送到运行时上下文范围链的前端。至于这个例子中compare()函数的运行时上下文,它的作用域链包含两个变量对象:compare()的激活对象和全局变量对象。

对于简单的范围链,情况就是这样,但是闭包的情况会有所不同。

封闭范围链

//step1:定义createComparisonFunction createComparisonFunction(property name){返回函数(object1,object 2){ var value 1=object 1[property name];var value 2=object 2[PrOperty name];if(value 1 value 2){ return-1;} else if(value 1 value 2){ return 1;} else { return 0;} };}//step2:调用createComparisonFunctionvar compare=createComparisonFunction(' name ');//step3:调用compare var result=compare({ name : ' Nicholas ' },{ name : ' Gerg ' });//step 4: recycle memory compare的取消引用闭包=null我们通过以下步骤说明范围链:

步骤1:定义了createComparisonFunction;

创建createComparisonFunction后,可以调用createComparisonFunction,这样就保留了createComparisonFunction的一个Function对象;此时将对象保留在内存中:

1.全局对象

2.创建比较函数对象范围链

步骤2:执行createComparisonFunction;

在执行createComparisonFunction的过程中,首先会创建createComparisonFunction的运行时上下文对象ScopeChain活动对象,其次会创建一个闭包(匿名函数),该对象在函数执行时会保存在内存中:

1.globalobject2。函数对象scope Chang 3。运行时上下文对象scope Chang 4。createcomparisonFunction 5的活动对象。功能对象scopechan5 5。关闭(匿名)

执行createComparisonFunction时,将销毁createComparisonFunction的运行时上下文对象ScopeChain,但不会销毁createComparisonFunction的活动对象,因为它被Closure(匿名)对象的ScopeChain引用。

函数执行后将对象保存在内存中:

1.globalobject2。createcomparisonfunctionscope Chang 3的Function对象。闭包(匿名)scope Chang 4的函数对象。createcomparisonfunction的活动对象

与步骤1相比,执行步骤2后,增加了两个对象:

1.闭包(匿名)scope Chang 2的Function对象。createcomparisonfunction的活动对象

原因是执行createComparisonFunction生成的闭包被compare引用,这个闭包函数的作用域链引用了createComparisonFunction的活动对象,所以这两个对象在内存中增加了。

步骤3:执行比较;

当执行闭包(比较)时,将首先创建闭包的运行时上下文对象ScopeChain活动对象,然后执行闭包。

执行闭包时将对象保留在内存中:

1.globalobject2。createcomparisonfunction的Function对象scopechan3。闭包闭包(匿名)函数对象scope Chang 4。createcomparisonfunction 5的活动对象。闭包closure(匿名)scope Chang 6的运行时上下文。闭包的活动对象(匿名)

执行闭包closure(匿名)后,Closure(匿名)的活动对象将被销毁,Closure(匿名)的运行时上下文范围链也将被销毁。

闭包执行后,将对象保存在内存中:

1.globalobject2。createcomparisonFunction的函数对象scopechan3。闭包的函数对象scopechan4(匿名)。createcomparisonfunction的活动对象

与步骤2相比,执行步骤3后,内存中保留的对象数量不会增加,这是一个函数正常执行时的情况。

正常情况下,执行一个函数后,保留在内存中的对象应该和执行前一样。

因为没有引入新的引用,所以保留在内存中的对象保持一致。

那么问题来了,createComparisonFunction的活动对象怎么销毁?

createComparisonFunction的活动对象之所以存在,是因为Closure(匿名)的Function对象的作用域链引用了createComparisonFunction的活动对象,其目的是访问createComparisonFunction,propertyName活动对象中的属性。

如果闭包的函数对象(匿名)被销毁,createComparisonFunction的活动对象也将被销毁,因为它没有被任何对象引用。

第四步取消对闭包比较的引用,这使得闭包不被任何对象引用并销毁,这样createComparisonFunction的活动对象也会因为没有被任何对象引用而被销毁,从而恢复这些对象占用的内存。

使用闭包的问题是内存消耗比普通函数大。因为需要保存额外的活动对象,所以当不需要闭包时,有必要取消引用闭包并回收额外活动对象占用的内存。

步骤4后保留在内存中的对象:

1.全局对象

2.createcomparisonfunction的函数对象范围链

与步骤1相比,步骤4执行后,内存中没有多余的对象,引用闭包产生的多余对象全部回收。

更多对JavaScript相关内容感兴趣的读者可以查看本网站专题:《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》、《JavaScript数学运算用法总结》、0103010

希望本文对JavaScript编程有所帮助。

版权声明:JavaScript范围链示例的详细说明是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。