知识大全 基于javascript 闭包基础分享

Posted 函数

篇首语:每个牛逼的人,都有一段苦逼的坚持。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 基于javascript 闭包基础分享相关的知识,希望对你有一定的参考价值。

  如果对作用域 函数为独立的对象这样的基本概念理解较好的话 理解闭包的概念并在实际的编程实践中应用则颇有水到渠成之感 在DOM的事件处理方面 大多数程序员甚至自己已经在使用闭包了而不自知 在这种情况下 对于浏览器中内嵌的JavaScript引擎的bug可能造成内存泄漏这一问题姑且不论 就是程序员自己调试也常常会一头雾水 用 简单的语句来描述JavaScript中的闭包的概念 由于JavaScript中 函数是对象 对象是属性的集合 而属性的值又可以是对象 则在函数内 定义函数成为理所当然 如果在函数func内部声明函数inner 然后在函数外部调用inner 这个过程即产生了一个闭包    闭包的特性 我们先来看一个例子 如果不了解JavaScript的特性 很难找到原因

复制代码 代码如下: var outter = [];         function clouseTest()             var array = ["one" "o" "three" "four"];             for (var i = ; i < array length; i++)                 var x = ;                 x no = i;                 x text = array[i];                 x invoke = function ()                     print(i);                                 outter push(x);                             //调用这个函数         clouseTest();         print(outter[ ] invoke());         print(outter[ ] invoke());         print(outter[ ] invoke());         print(outter[ ] invoke());

   运行的结果如何呢?很多初学者可能会得出这样的答案 然而 运行这个程序 得到的结果为 其 实 在每次迭代的时候 这样的语句x invoke = function()print(i);并没有被执行 只是构建了一个函数体为”print(i);”的函数对象 如此而已 而当i= 时 迭代停 止 外部函数返回 当再去调用outter[ ] invoke()时 i的值依旧为 因此outter数组中的每一个元素的invoke都返回i的 值 如何解决这一问题呢?我们可以声明一个匿名函数 并立即执行它

复制代码 代码如下: var outter = [];         function clouseTest ()             var array = ["one" "o" "three" "four"];             for (var i = ; i < array length; i++)                 var x = ;                 x no = i;                 x text = array[i];                 x invoke = function (no)                     return function ()                         print(no);                                     (i);                 outter push(x);                             clouseTest ();     </script>

   这个例子中 我们为x invoke赋值的时候 先运行一个可以返回一个函数的函数 然后立即执行之 这样 x invoke的每一次迭代器时相当与执行这样的语句

复制代码 代码如下: //x == x invoke = function()print( ); //x == x invoke = function()print( ); //x == x invoke = function()print( ); //x == x invoke = function()print( );

   这样就可以得到正确结果了 闭包允许你引用存在于外部函数中的变量 然而 它并不是使用该变量创建时的值 相反 它使用外部函数中该变量最后的值 闭包的用途 现在 闭包的概念已经清晰了 我们来看看闭包的用途 事实上 通过使用闭包 我们可以做很多事情 比如模拟面向对象的代码风格 更优雅 更简洁的表达出代码 在某些方面提升代码的执行效率 缓存 再来看一个例子 设想我们有一个处理过程很耗时的函数对象 每次调用都会花费很长时间 那么我们就需要将计算出来的值存储起来 当调用这个函数的时候 首先在缓存中查找 如果找不到 则进行计算 然后更新缓存并返回值 如果找到了 直接返回查找到的值即可 闭包正是可以做到这一点 因为它不会释放外部的引用 从而函数内部的值可以得以保留

复制代码 代码如下: var CachedSearchBox = (function ()             var cache =                count = [];             return                 attachSearchBox: function (dsid)                     if (dsid in cache) //如果结果在缓存中                         return cache[dsid];//直接返回缓存中的对象                                         var fsb = document getElementById(dsid);//新建                     cache[dsid] = fsb;//更新缓存                     if (count length > ) //保正缓存的大小<=                         delete cache[count shift()];                                         return fsb;                                 clearSearchBox: function (dsid)                     if (dsid in cache)                         cache[dsid] clearSelection();                                                 ;         )();         var obj = CachedSearchBox attachSearchBox("input ");         //alert(obj );         var obj = CachedSearchBox attachSearchBox("input ");

   实现封装

复制代码 代码如下: var person = function()     //变量作用域为函数内部 外部无法访问     var name = "default";       return        getName : function()            return name;               setName : function(newName)            name = newName;            (); print(person name);//直接访问 结果为undefined print(person getName()); person setName("jack"); print(person getName());

   得到结果如下 undefined default jack

  闭包的另一个重要用途是实现面向对象中的对象 传统的对象语言都提供类的模板机制 这样不同的对象(类的实例)拥有独立的成员及状态 互不干涉 虽然JavaScript中没有类这样的机制 但是通过使用闭包 我们可以模拟出这样的机制 还是以上边的例子来讲

复制代码 代码如下: function Person()     var name = "default";       return        getName : function()            return name;               setName : function(newName)            name = newName;            ; var john = Person(); print(john getName()); john setName("john"); print(john getName()); var jack = Person(); print(jack getName()); jack setName("jack"); print(jack getName());

   运行结果如下 default john default jack

  javascript闭包应该注意的问题 内存泄漏 在 不同的JavaScript解释器实现中 由于解释器本身的缺陷 使用闭包可能造成内存泄漏 内存泄漏是比较严重的问题 会严重影响浏览器的响应速度 降 低用户体验 甚至会造成浏览器无响应等现象 JavaScript的解释器都具备垃圾回收机制 一般采用的是引用计数的形式 如果一个对象的引用计数为 零 则垃圾回收机制会将其回收 这个过程是自动的 但是 有了闭包的概念之后 这个过程就变得复杂起来了 在闭包中 因为局部的变量可能在将来的某些时刻 需要被使用 因此垃圾回收机制不会处理这些被外部引用到的局部变量 而如果出现循环引用 即对象A引用B B引用C 而C又引用到A 这样的情况使得垃圾 回收机制得出其引用计数不为零的结论 从而造成内存泄漏 上下文的引用

复制代码 代码如下: $(function()     var con = $("div#panel");     this id = "content";     con click(function()        alert(this id);//panel     ); );

   此处的alert(this id)到底引用着什么值呢?很多开发者可能会根据闭包的概念 做出错误的判断 content 理 由是 this id显示的被赋值为content 而在click回调中 形成的闭包会引用到this id 因此返回值为content 然而事实 上 这个alert会弹出”panel” 究其原因 就是此处的this 虽然闭包可以引用局部变量 但是涉及到this的时候 情况就有些微妙了 因为 调用对象的存在 使得当闭包被调用时(当这个panel的click事件发生时) 此处的this引用的是con这个jQuery对象 而匿名函数中的 this id = “content”是对匿名函数本身做的操作 两个this引用的并非同一个对象 如果想要在事件处理函数中访问这个值 我们必须做一些改变

复制代码 代码如下: $(function()     var con = $("div#panel");     this id = "content";     var self = this;     con click(function()        alert(self id);//content     ); ); cha138/Article/program/Java/JSP/201311/20159

相关参考

知识大全 JavaScript自执行闭包的小例子

JavaScript自执行闭包的小例子  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!JQuery是

知识大全 JavaScript的模块化:封装(闭包),继承(原型) 介绍

JavaScript的模块化:封装(闭包),继承(原型)介绍  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看

知识大全 JavaScript中的关键字VAR使用详解 分享

JavaScript中的关键字VAR使用详解分享  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!JS

知识大全 javascript中自定义对象的属性方法分享

这篇文章介绍了在javascript中自定义对象的属性方法有需要的朋友可以参考一下   首先介绍下关联数组复制代码代码如下:<script>vartest=newObject()

知识大全 JavaScript 函数参数是传值(byVal)还是传址(byRef) 分享

JavaScript函数参数是传值(byVal)还是传址(byRef)分享  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我

知识大全 基于JavaScript 下namespace 功能的简单分析

基于JavaScript下namespace功能的简单分析  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一

知识大全 JavaScript 操作table,可以新增行和列并且隔一行换背景色代码分享

JavaScript操作table,可以新增行和列并且隔一行换背景色代码分享  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让

知识大全 Javascript 继承实现方式

Javascript继承实现方式  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  面向对象与基于对

知识大全 Java基础 JavaScript和Java的区别详细说明

Java基础JavaScript和Java的区别详细说明  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下

知识大全 javascript基础之查找元素的详细介绍

  当然这些选择器都是jQuery扩展的一些方法那么使用原生js时要怎样来查找元素呢?今天就来简单梳理下DOM定义了多种查找元素的方法除了我们常用的getElementById()还有getEleme