




已阅读5页,还剩5页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
详谈JavaScript 匿名函数及闭包1、匿名函数函数是JavaScript中最灵活的一种对象,这里只是讲解其匿名函数的用途。匿名函数:就是没有函数名的函数。1.1 函数的定义,首先简单介绍一下函数的定义,大致可分为三种方式第一种:这也是最常规的一种 代码如下:function double(x) return 2 * x; 第二种:这种方法使用了Function构造函数,把参数列表和函数体都作为字符串,很不方便,不建议使用。 代码如下:var double = new Function(x, return 2 * x;);第三种:var double = function(x) return 2* x; 注意“=”右边的函数就是一个匿名函数,创造完毕函数后,又将该函数赋给了变量square。1.2 匿名函数的创建第一种方式:就是上面所讲的定义square函数,这也是最常用的方式之一。第二种方式: 代码如下:(function(x, y) alert(x + y); )(2, 3);这里创建了一个匿名函数(在第一个括号内),第二个括号用于调用该匿名函数,并传入参数。2、闭包闭包的英文单词是closure,这是JavaScript中非常重要的一部分知识,因为使用闭包可以大大减少我们的代码量,使我们的代码看上去更加清晰等等,总之功能十分强大。闭包的含义:闭包说白了就是函数的嵌套,内层的函数可以使用外层函数的所有变量,即使外层函数已经执行完毕(这点涉及JavaScript作用域链)。示例一 代码如下:function checkClosure() var str = rain-man; setTimeout( function() alert(str); /这是一个匿名函数 , 2000);checkClosure();这个例子看上去十分的简单,仔细分析下它的执行过程还是有许多知识点的:checkClosure函数的执行是瞬间的(也许用时只是0.00001毫秒),在checkClosure的函数体内创建了一个变量str,在checkClosure执行完毕之后str并没有被释放,这是因为setTimeout内的匿名函数存在这对str的引用。待到2秒后函数体内的匿名函数被执行完毕,str才被释放。示例二,优化代码 代码如下:function forTimeout(x, y) alert(x + y);function delay(x , y , time) setTimeout(forTimeout( + x + , + y + ) , time); /* * 上面的delay函数十分难以阅读,也不容易编写,但如果使用闭包就可以让代码更加清晰 * function delay(x , y , time) * setTimeout( * function() * forTimeout(x , y) * * , time); * */ 3、举例匿名函数最大的用途是创建闭包(这是JavaScript语言的特性之一),并且还可以构建命名空间,以减少全局变量的使用。示例三: 代码如下:var oEvent = ;(function() var addEvent = function() /*代码的实现省略了*/ ; function removeEvent() oEvent.addEvent = addEvent; oEvent.removeEvent = removeEvent;)();在这段代码中函数addEvent和removeEvent都是局部变量,但我们可以通过全局变量oEvent使用它,这就大大减少了全局变量的使用,增强了网页的安全性。 我们要想使用此段代码:oEvent.addEvent(document.getElementById(box) , click , function();示例四: 代码如下:var rainman = (function(x , y) return x + y;)(2 , 3);/* * 也可以写成下面的形式,因为第一个括号只是帮助我们阅读,但是不推荐使用下面这种书写格式。 * var rainman = function(x , y) * return x + y; * (2 , 3); */在这里我们创建了一个变量rainman,并通过直接调用匿名函数初始化为5,这种小技巧有时十分实用。示例五: 代码如下:var outer = null;(function() var one = 1; function inner () one += 1; alert(one); outer = inner;)();outer(); /2outer(); /3outer(); /4这段代码中的变量one是一个局部变量(因为它被定义在一个函数之内),因此外部是不可以访问的。但是这里我们创建了inner函数,inner函数是可以访问变量one的;又将全局变量outer引用了inner,所以三次调用outer会弹出递增的结果。4、注意4.1 闭包允许内层函数引用父函数中的变量,但是该变量是最终值示例六: 代码如下:/* * * * one * two * three * one * */var lists = document.getElementsByTagName(li);for(var i = 0 , len = lists.length ; i len ; i+) lists i .onmouseover = function() alert(i); ;你会发现当鼠标移过每一个li&rt;元素时,总是弹出4,而不是我们期待的元素下标。这是为什么呢?注意事项里已经讲了(最终值)。显然这种解释过于简单,当mouseover事件调用监听函数时,首先在匿名函数( function() alert(i); )内部查找是否定义了 i,结果是没有定义;因此它会向上查找,查找结果是已经定义了,并且i的值是4(循环后的i值);所以,最终每次弹出的都是4。解决方法一: 代码如下:var lists = document.getElementsByTagName(li);for(var i = 0 , len = lists.length ; i len ; i+) (function(index) lists index .onmouseover = function() alert(index); ; )(i);解决方法二: 代码如下:var lists = document.getElementsByTagName(li);for(var i = 0, len = lists.length; i len; i+) lists i .$index = i; /通过在Dom元素上绑定$index属性记录下标 lists i .onmouseover = function() alert(this.$index); ;解决方法三: 代码如下:function eventListener(list, index) list.onmouseover = function() alert(index); ;var lists = document.getElementsByTagName(li);for(var i = 0 , len = lists.length ; i len ; i+) eventListener(lists i , i);4.2 内存泄露使用闭包十分容易造成浏览器的内存泄露,严重情况下会是浏览器挂死。可以参考下面内容预防:JavaScript垃圾回收机制 JavaScript不需要手动地释放内存,它使用一种自动垃圾回收机制(garbage collection)。当一个对象无用的时候,即程序中无变量引用这个对象时,就会从内存中释放掉这个变量。复制代码 代码如下: var s = 1, 2 ,3; var s = null; /这样原始的数组1 ,2 ,3就会被释放掉了。3、循环引用 三个对象 A 、B 、C ABC :A的某一属性引用着B,同样C也被B的属性引用着。如果将A清除,那么B、C也被释放。 ABCB :这里增加了C的某一属性引用B对象,如果这是清除A,那么B、C不会被释放,因为B和C之间产生了循环引用。复制代码 代码如下: var a = ; = a:100 ; = b:100 ; a = null ; /这种情况下,a:100和b:100就同时也被释放了。 var obj = ; = a : 100 ; = b : 200 ; var two = ; obj = null; /这种情况下 b:200不会被释放掉,而a:100被释放了。4、循环引用和闭包复制代码 代码如下: function outer() var obj = ; function inner() /这里引用了obj对象 obj.inner = inner; 这是一种及其隐蔽的循环引用,。当调用一次outer时,就会在其内部创建obj和inner两个对象,obj的inner属性引用了inner;同样inner也引用了obj,这是因为obj仍然在innerFun的封闭环境中,准确的讲这是由于JavaScript特有的“作用域链”。因此,闭包非常容易创建循环引用,幸运的是JavaScript能够很好的处理这种循环引用。5、IE中的内存泄漏 IE中的内存泄漏有好几种,这里有详细的解释(/en-us/library/bb250448.aspx)。 这里只讨论其中一种,即循环引用所造成的内存泄漏,因为,这是一种最普遍的情况。 当在DOM元素或一个ActiveX对象与普通JavaScript对象之间存在循环引用时,IE在释放这类变量时存在特殊的困难,最好手动切断循环引用,这个bug在IE 7中已经被修复了(/blog/archives/2006/04/ie_7_and_javasc.html)。 “IE 6 suffered from memory leaks when a circular reference between several objects, among which at least one DOM node, was created. This problem has been solved in IE 7. ” 如果上面的例子(第4点)中obj引用的不是一个JavaScript Function对象(inner),而是一个ActiveX对象或Dom元素,这样在IE中所形成的循环引用无法得到释放。复制代码 代码如下: function init() var elem = document.getElementByid( id ); elem.onclick = function() alert(rain-man); /这里引用了elem元素 ; Elem引用了它的click事件的监听函数,同样该函数通过其作用域链也引用回了elem元素。这样在IE中即使离开当前页面也不会释放这些循环引用。6、解决方法 基本的方法就是手动清除这种循环引用,下面一个十分简单的例子,实际应用时可以自己构建一个addEvent()函数,并且在window的unload事件上对所有事件绑定进行清除。复制代码 代码如下: function outer() var one = document.getElementById( one ); one.onclick = function(); window.onunload = function() var one = document.getElementById( one ); one.onclick = null; ;其它方法(by:Douglas Crockford)复制代码 代码如下:/* 遍历某一元素节点及其所有后代元素* param Elem node 所要清除的元素节点* param function func 进行处理的函数* */function walkTheDOM(node, func) func(node); node = node.firstChild; while
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 设备检修安全管理制度
- 设备等级评估管理制度
- 2025年中国家庭影院立体声接收器行业市场全景分析及前景机遇研判报告
- 设计成果运用管理制度
- 评估公司价格管理制度
- 诊所医疗软件管理制度
- 诊所财务制度管理制度
- 贝壳门店分级管理制度
- 财务集中中心管理制度
- 账务实物分开管理制度
- GB/T 16288-2024塑料制品的标志
- 高三一轮复习训练 湖泊专题
- 医院培训课件:《肩周炎》
- 安全生产月关爱生命注意安全
- 2024年中国家用水处理机市场调查研究报告
- 2024年版《输变电工程标准工艺应用图册》
- 肌少症的诊治浅析
- 2024年海南省中考数学试卷真题及答案详解(精校打印)
- 三菱FX3u-PLC应用实例教程全套课件配套课件完整版电子教案
- DL∕T 788-2016 全介质自承式光缆
- 陕西省安康市石泉县2023-2024学年八年级下学期期末考试物理试题
评论
0/150
提交评论