理解javascript闭包

原文:理解javascript闭包

1.闭包是什么

官方解释:闭包是一个拥有很多变量和绑定了这些变量的环境的表达式(其实就是函数),因而这些变量也是该表达式的一部分。这个定义虽然太学术,但是告诉我们两个信息:

1)闭包是一个函数

2)函数中有很多变量

上面两个是构成闭包的两个主要条件。

下面我们用通俗的话来解释一下:js中的所有函数都是闭包(因为函数中的局部变量只能函数内部访问),但是嵌套函数产生的闭包更加强大,也是我们现在所探讨的闭包。

如果上面的解释还不够通俗,下面的终极解释我想你一定能够看懂:

有一个函数a,函数a中嵌套了一个函数b,如果函数b被函数a外部的一个变量引用,就创建了一个闭包。

下面我们来看看具体如何通过代码来创建闭包,以加深上面概念的理解。

2.创建闭包

在创建闭包之前,首先要明白两个概念,一个是变量的作用域,一个事js中的作用域链,第一点我们简单说一下,第二点自己去查资料。

在Js中变量根据作用域的不同可以分为全局变量和局部变量(事实上很多语言都是这样),在js中,如果一个变量没有定义在任何函数中,则为全局变量;相对应的,定义在函数中的变量就是局部变量,但是如果函数中变量在声明时没有使用var关键字,则其仍然会称为全局变量。我们来看例子。

 

function f() {
            a = 1;//没有使用var,所以在函数外部也可以访问
        }
        f();
        alert(a);

  

下面我们看看如何创建闭包,看下面的函数

 

 

     function f1() {
            var a = 10;
            a++;
            alert(a);
        }
        var func1 = f1();
        func1;
        func1;

 

希望你能猜对上面代码的运行结果,只输出一个11。在函数f1的外部创建了变量func1,然后指向由函数f1的构造函数创建的对象。(在js中,你可以将函数看作是类,)。当执行完代码func1之后,这个对象就没有引用了,所以会被垃圾回收,对象中的变量a同样也会被回收;所以当再次执行func1时就不会有输出了。

 

从上面的代码,希望你能明白这样一个道理:js中是有垃圾回收机制的。当一个对象没有变量引用的时候,这个对象就会被回收。

再来看下面的代码:

 

function f1() {
            var a = 10;
            function f2() {
                a++;
                alert(a);
            }
            return f2;
        }
        var func1 = f1();
        func1();
        func1();

  

上面代码的输出结果为11,12。

 

执行完第一句func1()之后,对象应该被回收,第二句func1();应该没有输出猜对呢,这是为什么呢?

我们来分析一下。

首先看var func1=f1();这行代码执行之后,func1是什么。在函数f1中返回的是函数f2,所以func1的值其实是函数f2。按理说当执行完这行代码之后,函数f1的使命已经完成,应该被垃圾回收才是,你们变量a也会被清除,但是执行代码func1()之后的结果居然为11,这说明函数f1中的变量a没有被清除,那么肯定函数f1也没有被垃圾回收。这是为什么?

我们前面说过,一个对象如果被垃圾回收的条件是什么,那就是没有变量引用这个对象。我们来看看上面的代码。函数f2中对函数f1中的变量a进行++操作,也就是说在函数f2中引用了函数f1中的变量,也就是函数f2引用了函数f1。而代码var func1=f1();其实是将函数f2返回给变量func1,也就是说变量func1引用了函数f2,而函数f2由引用了函数f1,这种间接引用的结果就是函数f1一直被变量引用着,所以一直无法被垃圾回收。

上面的情况就是闭包,我们再回顾一下闭包的定义:如果函数a中的嵌套函数b被函数a外部的变量引用,就创建了闭包。

综合上面的讨论,我们可以看出闭包的作用是什么

3.闭包的作用

1)变量的安全性:我们无法在函数f1的外部直接访问其局部变量a,只能通过函数f2来访问,而在函数f2中我们可以写代码进行安全性的控制,这是不是和c#中类的属性很像。所以我们可以将函数f2看成是函数f1的一个属性,这个属性只有setter方法,而将局部变量a看成是函数f1的私有字段,只能通过公共属性f2才能访问f1中的私有字段a。

2)让变量的值始终保存在内存中。这个已经非常清晰了,通过闭包,函数f1中的变量a没有被回收,而是一直保存在内存中。

时间: 2024-09-11 02:24:55

理解javascript闭包的相关文章

全面理解Javascript闭包和闭包的几种写法及用途

原文:全面理解Javascript闭包和闭包的几种写法及用途 好久没有写博客了,过了一个十一长假都变懒了,今天总算是恢复状态了.好了,进入正题,今天来说一说javascript里面的闭包吧!本篇博客主要讲一些实用的东西,主要将闭包的写法.用法和用途. 一.什么是闭包和闭包的几种写法和用法                                                       1.什么是闭包 闭包,官方对闭包的解释是:一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函

深入理解javascript闭包

变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域 变量的作用域无非就是两种:全局变量和局部变量 Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量 var n=999; function f1(){ alert(++n); } f1(); // 1000 另一方面,在函数外部无法读取函数内的局部变量 function f1(){ var n=999; } alert(++n); // error 这里有一个地方需要注意,函数内部声明变量的时候,一定要

用最通俗易懂的代码帮助新手理解javascript闭包 推荐_javascript技巧

最近看了几篇有关javascript闭包的文章,包括最近正火的汤姆大叔系列,还有<javascript高级程序设计>中的文章,--我看不懂,里面有些代码是在大学教科书中看都没看过的,天书一般.幸好最近遇到两本好书<ppk on javascript>和<object-oriented JavaScript>,正字阅读中,后者还没有中文版,但前者还是建议看原版,写的不复杂,有兴趣的朋友可以看看,适合想进阶的朋友. 今天就结合这两本书,用最浅显的语言和最通俗的方式谈谈jav

深入理解javascript闭包的教程

1,闭包是什么 (百度百科定义)--闭包是可以包含自由(未绑定到特定对象)变量的代码块:这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义(局部变 量)."闭包" 一词来源于以下两者的结合:要执行的代码块(由于自由变量被包含在代码块中,这些自由变量以及它们引用的对象没有被释放)和为自由变量提供绑定的计算环境 (作用域).     W3C ECMAScript在闭包的解释中,有这么一句话:闭包,指的是词法表示包括不被计算的变量的函数,也就是说,函数可以使用

深入理解Javascript闭包 新手版_javascript技巧

一.什么是闭包? "官方"的解释是:所谓"闭包",指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分. 相信很少有人能直接看懂这句话,因为他描述的太学术.我想用如何在Javascript中创建一个闭包来告诉你什么是闭包,因为跳过闭包的创建过程直接理解闭包的定义是非常困难的.看下面这段代码: 复制代码 代码如下: function a(){ var i=0; function b(){ alert(++i); }

深入理解JavaScript 闭包究竟是什么_基础知识

1.简单的例子 首先从一个经典错误谈起,页面上有若干个div, 我们想给它们绑定一个onclick方法,于是有了下面的代码 复制代码 代码如下: <div id="divTest">        <span>0</span> <span>1</span> <span>2</span> <span>3</span>    </div>    <div id=&q

理解Javascript闭包_javascript技巧

闭包是ECMAScript一个很重要的特征,但是却很难用合适的定义来描述它.虽然闭包很难清晰地描述,但是,却很容易创建,或者说,不小心创建.然而,闭包的存在其实是有一定的潜在问题的.为了避免"不小心"地创建闭包,以及更好地利用闭包的优点,有必要理解闭包的机制. 闭包的定义 关于闭包,有太多的定义,特别是有一些定义非常抽象,象这个: A "closure" is an expression (typically a function) that can have fr

简单理解JavaScript闭包的笔记

## 1 JavaScript 函数允许你访问函数以外定义的变量 如果你清楚JavaScript的作用域链的概念,对于这条你就不难理解了. 大致的意思就是说,js寻找变量的定义会从最近的区域找起,本地找不到就往上一层区域 找,直到找到命名空间的顶端,在浏览器的世界里顶端就是window对象了.  代码如下 复制代码 example-1 var a_var_in_global_environment = "hello Closure" function func(){ console.l

JavaScript知识点总结(十六)之Javascript闭包(Closure)代码详解_javascript技巧

闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现.很早就接触过闭包这个概念了,但是一直糊里糊涂的,没有能够弄明白JavaScript的闭包到底是什么,有什么用,今天在网上看到了一篇讲JavaScript闭包的文章(原文链接),讲得非常好,这下算是彻底明白了JavaScript的闭包到底是个神马东东以及闭包的用途了,在此写出来和大家分享一下,希望不理解JavaScript闭包的朋友们看了之后能够理解闭包!以下内容大部分是来自原文,我在原文的基础