`

浅谈JavaScript闭包

 
阅读更多

Javascript Closure

 

为什么知道闭包很重要?

闭包是JS语言的难点也是其一大特色,很多初学者甚至从业多年的开发者也很难弄清楚这个概念。弄明白这个概念十分重要,因为不但是对学习JS语言的一个大提升,在编写高级应用时候经常要用到,同时也是很多面试题目中经常会考到的问题。

 

闭包的“官方”解释:

所谓“闭包”,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。
想必上述解释大部分人看起来都像是天书,要了解闭包首先我们还需要知道JS语言的作用域这个概念。

 

变量的作用域

函数内部可以直接读取全局变量。

var n=7;
function f1 () {
  alert(n);
}
f1();  // 7

 
在函数外部自然无法读取函数内的局部变量。

function f1 () {
  var n=7;
}
alert(n);  // error

 
这样牵扯出来一个问题:如何访问函数内部的变量呢 ?
我们先来看下面一个例子:

function f1() {

   var n = 7;
   function f2 (){
      alert(n);
   }
   return f2;
}

var result = f1();
result();  

这里就形成了闭包,由此我们可以给闭包一个新的解释。

 


闭包的“通俗”解释:

闭包就是能够读取其他函数内部变量的函数,其本质就是就是将函数内部和函数外部连接起来的一座桥梁。


(闭包是由函式和与其相关的参照环境组合而成的实体。即便在函数内部定义了函数,如果没有引用父函数作用域的变量,也照样可以不是闭包。函数和环境,缺一不可,这才是闭包。)

再看一个稍微复杂一点的例子:

var foo = ( function () {
    var secret = 'secret';
    return {
        get_secret: function () {
            return secret;
        }, 
new_secret: function (new_secret) {
            secret = new_secret;
        }
    };
}() );

foo.get_secret ();  // 得到 ‘secret'
foo.secret;   // Type error,访问不能
foo.new_secret ('a new secret');  // 通过函数接口,我们访问并修改了 secret 变量
foo.get_secret (); // 得到 'a new secret'

 

 


引用 Douglas Crockford [1] :
之所以可能通过这种方式在 JavaScript 种实现公有,私有,特权变量正是因为闭包,闭包是指在 JavaScript 中,内部函数总是可以访问其所在的外部函数中声明的参数和变量,即使在其外部函数被返回(寿命终结)了之后。

 

闭包主要应用场合主要是为了:设计私有的方法和变量。

 

function foo(x) {
    var tmp = 3;
    return function (y) {
        alert(x + y + (++tmp));
    }
}
var bar = foo(2); // bar 现在是一个闭包
bar(10);

 

 

闭包特点

闭包会把函数中的变量都被保存在内存中。

注意点

1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除
2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

 

参考资源

ECMA-262-3 in detail. Chapter 6. Closures.

[1] how do JavaScript closures work

[2] 学习Javascript闭包(Closure)

[3] 理解Javascript的闭包

[4] JavaScript:闭包和引用

[5] Private Members in JavaScript
 

 

 

该篇文章是公司技术分享会的演讲稿文字整理

分享到:
评论

相关推荐

    根据一段代码浅谈Javascript闭包

    } 这里的闭包是f1,封闭了一个变量n和一个函数f2。 我们先无视nAdd,尽量保持原貌重写一下这个函数。 代码如下: function f1(){ var n = 999; var f2 = function(){ alert(n); }; return f2; } var result ...

    浅谈JavaScript for循环 闭包_.docx

    浅谈JavaScript for循环闭包 在JavaScript中,for循环和闭包是两个非常重要的概念。本文将对JavaScript for循环和闭包进行浅谈,并提供六种解决方案来解决for循环中的闭包问题。 首先,让我们来看一个例子。我们有...

    浅谈js 闭包引起的内存泄露问题

    在JavaScript编程中,闭包是一个非常重要的概念,它的特性使得函数可以访问到外部函数作用域中的变量。然而,闭包如果使用不当,非常容易引起...通过以上措施,可以最大限度地减少JavaScript闭包所带来的内存泄漏问题。

    浅谈JavaScript的闭包函数

    闭包在JavaScript中是一个至关重要的概念,它常常让人困惑,有时甚至被误认为与匿名函数相同。实际上,闭包是一种特殊的函数,它具备访问并存储其父级(或外部)函数作用域中变量的能力,即使在父级函数执行完毕后,...

    浅谈javascript的闭包

    JavaScript中的闭包是一种强大的特性,它允许函数访问和操作其外部作用域的变量,即使在其外部函数已经执行完毕的情况下。这种现象是由于JavaScript的作用域链机制以及函数内部环境的持久存在性导致的。 首先,我们...

    浅谈javascript面向对象编程

    ### 浅谈JavaScript面向对象编程 #### 一、概述 面向对象编程(OOP)是一种编程范式,它使用“对象”来设计软件。在JavaScript中,尽管语言本身并不支持传统的类(class)概念,但开发者可以通过原型继承和其他技术来...

    【JavaScript源代码】浅谈react useEffect闭包的坑.docx

    在JavaScript中,闭包是指能够读取其他函数内部变量的函数。在本例中,问题出现在`useEffect`中注册的点击事件处理器函数`clickHandle`能够访问外部作用域中的变量`v`。这种现象在某些情况下可能导致预料之外的结果...

    浅谈javascript中的闭包

    Javascript中有几个非常重要的语言特性——对象、原型继承、闭包。其中闭包 对于那些使用传统静态...本文将以例子入手来介绍Javascript闭包的语言特性,并结合一点 ECMAScript语言规范来使读者可以更深入的理解闭包。

    浅谈js闭包理解

    在JavaScript中,闭包是一种强大的特性,它允许函数访问并操作其外部作用域中的变量,即使在其外部函数已经执行完毕之后。这种特性使得闭包成为实现数据隐藏、封装和持久化状态的有效工具。 首先,让我们深入理解...

    浅谈JavaScript for循环 闭包

    这些解决方案展示了JavaScript闭包和作用域的复杂性,以及如何通过不同的技术手段来控制函数作用域内的变量访问。在实际的前端开发工作中,根据具体情况选择合适的解决方案是非常重要的。对for循环和闭包的理解能够...

    浅谈Javascript嵌套函数及闭包

    在探讨JavaScript嵌套函数及闭包之前,我们必须了解一些基础知识。首先是JavaScript中的函数,它们是JavaScript编程的核心。函数在JavaScript中是“一等公民”,这意味着函数可以作为参数传递给其他函数,也可以作为...

    浅谈JavaScript作用域和闭包

    作用域和闭包是JavaScript语言中至关重要的概念,它们决定了变量和函数的可见性和生命周期。在JavaScript中,作用域可以分为全局作用域和局部作用域两大类,而闭包则是函数和声明该函数的词法环境的组合。下面将详细...

    浅谈JS闭包中的循环绑定处理程序

    这正是JavaScript闭包的强大之处,它允许我们创建具有持久状态的函数,即使这些函数是在其他函数的上下文中定义的。 理解闭包在循环绑定处理程序中的应用是JavaScript开发中的重要概念,它可以帮助我们避免一些常见...

Global site tag (gtag.js) - Google Analytics