问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

闭包函数的应用范围

发布网友 发布时间:2022-04-20 18:18

我来回答

1个回答

热心网友 时间:2022-04-20 19:47

对这个问题的回答可能会令你惊讶--闭包什么都可以做。据我所知,闭包使得 ECMAScript 能够模仿任何事物,因此局限性在于设计和实现要模仿事物的能力。只是从字面上看可能会觉得这么说很深奥,下面我们就来看一些更有实际意义的例子。
例 1:为函数引用设置延时
闭包的一个常见用法是在执行函数之前为要执行的函数提供参数。例如:将函数作为 setTimout 函数的第一个参数,这在 Web 浏览器的环境下是非常常见的一种应用。
setTimeout 用于有计划地执行一个函数(或者一串 JavaScript 代码,不是在本例中),要执行的函数是其第一个参数,其第二个参数是以毫秒表示的执行间隔。也就是说,当在一段代码中使用 setTimeout 时,要将一个函数的引用作为它的第一个参数,而将以毫秒表示的时间值作为第二个参数。但是,传递函数引用的同时无法为计划执行的函数提供参数。
然而,可以在代码中调用另外一个函数,由它返回一个对内部函数的引用,再把这个对内部函数对象的引用传递给 setTimeout 函数。执行这个内部函数时要使用的参数在调用返回它的外部函数时传递。这样,setTimeout 在执行这个内部函数时,不用传递参数,但该内部函数仍然能够访问在调用返回它的外部函数时传递的参数:
function callLater(paramA, paramB, paramC){
/* 返回一个由函数表达式创建的匿名内部函数的引用:- */
return (function(){
/* 这个内部函数将通过 - setTimeout - 执行,
而且当它执行时它会读取并按照传递给
外部函数的参数行事:
*/
paramA[paramB] = paramC;
});
}
...
/* 调用这个函数将返回一个在其执行环境中创建的内部函数对象的引用。
传递的参数最终将作为外部函数的参数被内部函数使用。
返回的对内部函数的引用被赋给一个全局变量:-
*/
var functRef = callLater(elStyle, display, none);
/* 调用 setTimeout 函数,将赋给变量 - functRef -
的内部函数的引用作为传递的第一个参数:- */
hideMenu=setTimeout(functRef, 500);
例 2: 通过对象实例方法关联函数
回到顶部
许多时候我们需要将一个函数对象暂时挂到一个引用上留待后面执行,因为不等到执行的时候是很难知道其具体参数的,而先前将它赋给那个引用的时候更是压根不知道的。 (此段由 pangba 刘未鹏 翻译)
(luyy朋友的翻译_2008-7-7更新)很多时候需要将一个函数引用进行赋值,以便在将来某个时候执行该函数,在执行这些函数时给函数提供参数将会是有用处的,但这些参数在执行时不容易获得,他们只有在上面赋值给时才能确定。
(原文备考:There are many other circumstances when a reference to a function object is assigned so that it would be executed at some future time where it is useful to provide parameters for the execution of that function that would not be easily available at the time of execution but cannot be known until the moment of assignment.)
一个相关的例子是,用 JavaScript 对象来封装与特定 DOM 元素的交互。这个 JavaScript 对象具有 doOnClick、doMouseOver 和 doMouseOut 方法,并且当用户在该特定的 DOM 元素中触发了相应的事件时要执行这些方法。不过,可能会创建与不同的 DOM 元素关联的任意数量的 JavaScript 对象,而且每个对象实例并不知道实例化它们的代码将会如何操纵它们(即注册事件处理函数与定义相应的事件处理函数分离。译者注)。这些对象实例并不知道如何在全局环境中引用它们自身,因为它们不知道将会指定哪个全局变量(如果有)引用它们的实例。
因而问题可以归结为执行一个与特定的 JavaScript 对象关联的事件处理函数,并且要知道调用该对象的哪个方法。
下面这个例子使用了一个基于闭包构建的一般化的函数(此句多谢未鹏指点),该函数会将对象实例与 DOM 元素事件关联起来,安排执行事件处理程序时调用对象实例的指定方法,给象的指定方法传递的参数是事件对象和与元素关联的引用,该函数返回执行相应方法后的返回值。
/* 一个关联对象实例和事件处理器的函数。
它返回的内部函数被用作事件处理器。对象实例以 - obj - 参数表示,
而在该对象实例中调用的方法名则以 - methodName - (字符串)参数表示。
*/
function associateObjWithEvent(obj, methodName){
/* 下面这个返回的内部函数将作为一个 DOM 元素的事件处理器*/
return (function(e){
/* 在支持标准 DOM 规范的浏览器中,事件对象会被解析为参数 - e - ,
若没有正常解析,则使用 IE 的事件对象来规范化事件对象。
*/
e = e||window.event;
/* 事件处理器通过保存在字符串 - methodName - 中的方法名调用了对象
- obj - 的一个方法。并传递已经规范化的事件对象和触发事件处理器的元素
的引用 - this - (之所以 this 有效是因为这个内部函数是作为该元素的方法执行的)
*/
return obj[methodName](e, this);
});
}
/* 这个构造函数用于创建将自身与 DOM 元素关联的对象,
DOM 元素的 ID 作为构造函数的字符串参数。
所创建的对象会在相应的元素触发 _disibledevent= function(){
... // 方法体。
};
Internet Explorer 的内存泄漏问题
Internet Explorer Web 浏览器(在 IE 4 到 IE 6 中核实)的垃圾收集系统中存在一个问题,即如果 ECMAScript 和某些宿主对象构成了 循环引用,那么这些对象将不会被当作垃圾收集。此时所谓的宿主对象指的是任何 DOM 节点(包括 document 对象及其后代元素)和 ActiveX 对象。如果在一个循环引用中包含了一或多个这样的对象,那么这些对象直到浏览器关闭都不会被释放,而它们所占用的内存同样在浏览器关闭之前都不会交回系统重用。
当两个或多个对象以首尾相连的方式相互引用时,就构成了循环引用。比如对象 1 的一个属性引用了对象 2 ,对象 2 的一个属性引用了对象 3,而对象 3 的一个属性又引用了对象 1。对于纯粹的 ECMAScript 对象而言,只要没有其他对象引用对象 1、2、3,也就是说它们只是相互之间的引用,那么仍然会被垃圾收集系统识别并处理。但是,在 Internet Explorer 中,如果循环引用中的任何对象是 DOM 节点或者 ActiveX 对象,垃圾收集系统则不会发现它们之间的循环关系与系统中的其他对象是隔离的并释放它们。最终它们将被保留在内存中,直到浏览器关闭。
闭包非常容易构成循环引用。如果一个构成闭包的函数对象被指定给,比如一个 DOM 节点的事件处理器,而对该节点的引用又被指定给函数对象作用域中的一个活动(或可变)对象,那么就存在一个循环引用。DOM_Node.onevent ->function_object.[[scope]] ->scope_chain ->Activation_object.nodeRef ->DOM_Node。形成这样一个循环引用是轻而易举的,而且稍微浏览一下包含类似循环引用代码的网站(通常会出现在网站的每个页面中),就会消耗大量(甚至全部)系统内存。
多加注意可以避免形成循环引用,而在无法避免时,也可以使用补偿的方法,比如使用 IE 的 onunload 事件来来清空(null)事件处理函数的引用。时刻意识到这个问题并理解闭包的工作机制是在 IE 中避免此类问题的关键。

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
为什么来大姨妈胸会胀 少儿学什么舞蹈 青年学什么舞蹈好 成年人学什么舞蹈 福州企业最低工资标准 2013年厦门的底薪是多少 生产要素的需求有哪些性质 生产要素的需求有何特点? 什么是生产要素需求 微观经济学要素需求什么是条件要素需求?它和要素需求有什么不同?_百度... 关于美的一瞬间作文 餐厅服务员给主管怎样写请假条 我是在餐厅里做服务员的,每逢周五,周六,周日就是餐厅在一个礼拜里最忙的三天,我想明天周五晚上请半天 几个关于美的作文 在餐饮工作想请假用什么借口能请十天半月的 在餐厅工作想要请假提前一小时下班跟老板说可以的吗,另外要怎么说比较好? 朋友叫这去聚会 但是还要上班该怎么请假 在干餐饮 因为家了面的餐馆要办营业执照的请假条怎么写? 餐厅请假条怎么写? 我是餐饮行业的,休假不容易,写请假条的原因应该写什么。 酒店餐饮部请假条怎么写内容 什么是弱电??弱点有什么作用?? 什么叫弱电 幼儿园小班微笑宝贝的主要事迹怎么写? 一般证券客户资料都主要哪些? 微信下载怎么下载 有美国签证可以免签去新西兰吗 全国有几家互联网 鹿树下野参行的参都是多少年份的? 鹿树下野山参怎么样?谁了解过? 试联系实际论述如何促进产业结构的优化升级? 今天是什么节气 二十四节气 如何加快转变经济发展方式推动产业结构优化升级 产业结构优化的升级 产业结构的优化升级 青少年卧室装修风格哪个比较好 有没有什么方法可以快速的学习初中的英语单词呢?有推荐的吗? 小卧室要怎么装修才是最实用的 小女孩的卧室怎么装修好看 在关公面前耍大刀 关公面前耍大刀,后面应该接什么? 与“关公面前耍大刀”类似的话还有什么? 闭包问题,为什么参数i弹出的是object mouseevent mastercamx9破解打开了,重启电脑又要激活码 梦见自己倒车撞高墙且墙倒出人命? ↗关于春节的作文 连着梦到被蜜蜂哲,被龙猫咬,还被玻璃茬扎是什么意思 被龙猫咬了!!!急!!! 被龙猫咬了 如果不慎被龙猫咬了该怎么办?