什么是闭包?闭包的优缺点

什么是闭包?闭包的优缺点?

闭包(closure)是javascript的一大难点,也是它的特色。很多高级应用都要依靠闭包来实现。

1、变量作用域

要理解闭包,首先要理解javascript的特殊的变量作用域。

变量的作用域无非就两种:全局变量和局部变量。

javascript语言的特别之处就在于:函数内部可以直接读取全局变量,但是在函数外部无法读取函数内部的局部变量。

注意点:在函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明的是一个全局变量!

2、如何从外部读取函数内部的局部变量?

出于种种原因,我们有时候需要获取到函数内部的局部变量。但是,上面已经说过了,正常情况下,这是办不到的!只有通过变通的方法才能实现。

那就是在函数内部,再定义一个函数。

function f1(){

    var n=999;

    function f2(){
      alert(n); // 999
    }

  }

在上面的代码中,函数f2就被包括在函数f1内部,这时f1内部的所有局部变量,对f2都是可见的。但是反过来就不行,f2内部的局部变量,对f1就是不可见的。

这就是Javascript语言特有的"链式作用域"结构(chain scope),

子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。

既然f2可以读取f1中的局部变量,那么只要把f2作为返回值,我们不就可以在f1外部读取它的内部变量了吗!

3、闭包的概念

上面代码中的f2函数,就是闭包。

各种专业文献的闭包定义都非常抽象,我的理解是: 闭包就是能够读取其他函数内部变量的函数。

由于在javascript中,只有函数内部的子函数才能读取局部变量,所以说,闭包可以简单理解成“定义在一个函数内部的函数“。

所以,在本质上,闭包是将函数内部和函数外部连接起来的桥梁。

 4、闭包的用途

闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中,不会在f1调用后被自动清除。

为什么会这样呢?原因就在于f1是f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。

这段代码中另一个值得注意的地方,就是"nAdd=function(){n+=1}"这一行,首先在nAdd前面没有使用var关键字,因此nAdd是一个全局变量,而不是局部变量。其次,nAdd的值是一个匿名函数(anonymous function),而这个匿名函数本身也是一个闭包,所以nAdd相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作。

5、使用闭包的注意点

(1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

(2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

时间: 2024-10-14 05:41:10

什么是闭包?闭包的优缺点的相关文章

递归,闭包,闭包与变量

递归是在一个函数内部调用自身: function factorial(num){ if(num<=1){ return 1; }else{ return num*factorial(num-1) } } 但是会出现问题: var fan=factorial; fun(4); factorial=null; 在调用fun(4)时,先执行上面的函数,到else内时,factorial已经被改了,所以得不到正确的结果. 使用arguments.callee代替函数就不会出错. 闭包: 创建函数时会预先

前端知识体系:JavaScript基础-作用域和闭包-闭包的实现原理和作用以及堆栈溢出和内存泄漏原理和相应解决办法

闭包的实现原理和作用 闭包: 有权访问另一个函数作用域中的变量的函数. 创建闭包的常见方式就是,在一个函数中创建另一个函数. 闭包的作用: 访问函数内部变量.保持函数在环境中一直存在,不会被垃圾回收机制处理 因为函数内部声明 的变量是局部的,只能在函数内部访问到,但是函数外部的变量是对函数内部可见的,这就是作用域链的特点了. 子级可以向父级查找变量,逐级查找,找到为止 因此我们可以在函数内部再创建一个函数,这样对内部的函数来说,外层函数的变量都是可见的,然后我们就可以访问到他的变量了. <scr

关于闭包的作用,以及优缺点

定义:闭包 当一个函数的返回值是另外一个函数,而返回的那个函数如果调用了其父函数内部的变量,且返回的这个函数在外部被执行         就产生了闭包.闭包是一个环境,具体指的就是外部函数--高阶函数. 说白了就是一个环境,能够读取其他函数内部的变量. 本质上,闭包是将函数内部和函数外部连接起来的桥梁. 用处:1.读取函数内部的变量: 2.这些变量的值始终保持在内存中,不会在外层函数调用后被自动清除. 优点:1:变量长期驻扎在内存中: 2:避免全局变量的污染: 3:私有成员的存在 : 特性:1:

多角度了解Javascript闭包

javascript的闭包是非常有用的特性,利用它可以实现很多功能,在学习闭包的过程中也想分享自己的一些理解和总结,于是写了此文. 闭包是什么?  ( 相关概念:匿名函数,执行环境,作用域链,变量对象,活动对象,this对象,内存泄露). 闭包(closure):有权访问另一个函数作用域中的变量的函数: 匿名函数(anonymous function):创建一个函数并将它赋值给变量functionName; 执行环境(execution context):定义了变量和函数访问其他数据和决定它们各

对js中闭包,作用域,原型的理解

前几天,和朋友聊天,聊到一些js的基础的时候,有一种‘好像知道,好像又不不知道怎么讲的感觉’...于是捡起书,自己理一理,欢迎拍砖. 闭包 理解闭包首先要理解,js垃圾回收机制,也就是当一个函数被执行完后,其作用域会被收回,如果形成了闭包,执行完后其作用域就不会被收回. 如果某个函数被他的父函数之外的一个变量引用,就会形成闭包 闭包的作用,就是保存自己私有的变量,通过提供的接口(方法)给外部使用,但外部不能直接访问该变量. 例子(使用闭包): var test=(function(){ var

14.匿名函数和闭包

匿名函数和闭包 学习要点:1.匿名函数2.闭包 匿名函数就是没有名字的函数,闭包是可以访问一个函数作用域里变量的函数.声明:本节内容需要有面向对象和少量设计模式基础. 一.匿名函数 //普通函数function box(){ //函数名是box return 'Lee'; } //匿名函数function(){ //匿名函数,会报错,单独的匿名函数是无法运行的 return 'Lee';} //通过表达式自我执行(function box(){ //封装成表达式 alert('Lee');})(

匿名函数和闭包

匿名函数和闭包匿名函数就是没有名字的函数,闭包是可访问一个函数作用域里变量的函数.一. 匿名函数//普通函数functionbox() { //函数名是 boxreturn'Lee';}//匿名函数function() { //匿名函数,会报错return'Lee';}//通过表达式自我执行(function box() { //封装成表达式alert('Lee');})(); //()表示执行函数,并且传参//把匿名函数赋值给变量var box = function() { //将匿名函数赋给

javascript的闭包

闭包闭包闭包,屁包屁包屁包 一.什么是闭包 javascript里面,所有的函数都是闭包! 这句断言真是惊天地,泣鬼神.不过,通常意义上的闭包是指:某个函数内部的子函数,这个子函数被外界所调用,用于访问父函数(就是那个该死的"某个函数"啦)内的变量(包括参数). 从中可以看出,我们常常说的闭包是: 1)首先,闭包是一个函数 2)其次,闭包是一个子函数,就是说,它是一个嵌套在函数里的子函数,函数中的函数 3)这个子函数有什么用呢?它会被外界访问,外界通过访问它来访问和操控它所在的父函数中

Python高阶函数-闭包

高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回. 在这里我们首先回忆一下python代码运行的时候遇到函数是怎么做的. 从python解释器开始执行之后,就在内存中开辟了一个空间 每当遇到一个变量的时候,就把变量名和值之间的对应关系记录下来. 但是当遇到函数定义的时候解释器只是象征性的将函数名读入内存,表示知道这个函数的存在了,至于函数内部的变量和逻辑解释器根本不关心. 等执行到函数调用的时候,python解释器会再开辟一块内存来存储这个函数里的内容,这个时候,才关注函数里面有哪

Swift:闭包

一.闭包的介绍 闭包表达式(Closure Expressions) 尾随闭包(Trailing Closures) 值捕获(Capturing Values) 闭包是引用类型(Closures Are Reference Types) 闭包是自包含的函数代码块,可以在代码中被传递和使用. Swift 中的闭包与 C 和 Objective-C 中的代码块(blocks)以及其他一些编程语言中的 lambdas 函数比较相似. 闭包可以捕获和存储其所在上下文中任意常量和变量的引用. 这就是所谓的