JavaScript闭包详解

JavaScript闭包详解

闭包就是由函数创造的一个词法作用域,里面创建的变量被引用后,可以在这个词法环境之外自由使用(维基百科)。

闭包,官方对闭包的解释是:一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。闭包的特点:   1. 作为一个函数变量的一个引用,当函数返回时,其处于激活状态。   2. 一个闭包就是当一个函数返回时,一个没有释放资源的栈区。

  简单的说,JavaScript允许使用内部函数—即函数定义和函数表达式位于另一个函数的函数体内。而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数和声明的其他内部函数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。

在JavaScript中,闭包通常用来创建函数内部的变量,使这些变量不能被外部随意修改,同时又可以通过指定的函数接口来操作。

JavaScript中,变量的作用域只有两种:

  1. 全局变量
  2. 局部变量

这样就存在一个问题,全局变量可以被所有的函数读写,而局部变量又只能被其所有者(函数)读写。那么如果现在我们需要在外部读写改函数内部时的局部变量时我们该怎么做?

看看下面这个例子:

    var add = (function (){
    var count = 0;
    return  function() { return count += 1; }
})();

add();
add();
add();
//count为3

这就是简单的一个闭包的例子,每次调用add都会使count加1。在这个例子中,匿名函数function(){ return count += 1; }可以访问其上层匿名函数所有的局部变量,而下层匿名函数的局部变量对上层又是不可见的。这就是JavaScript特有的“链式作用结构(chain scope)”,子对象可以一层一层地向上访问所有父对象地变量,但子对象地所有变量对父对象不可见。

因此我们把下层匿名函数作为返回值,就可以在匿名函数外部读取并操作它的内部变量。

事实上,就概念而言一个函数本身就是一个闭包,但函数嵌套函数这种类型的闭包作用更大,所以我们通常所用的闭包就是一个函数内嵌套一个返回自身的函数,并提供一个变量(上面的例子是add)作为接口来调用。这样做的直观效果是我们就可以在函数外部修改函数内部的变量了。

更深层次的是,这些可修改的局部变量会一只保存在内存中。下层匿名函数被赋值给一个变量(add),这使得下层匿名函数始终存在于内存中,而它又依赖于上层匿名函数,因此闭包机构所涉及的所有函数都不会在调用结束后被垃圾回收机制(garbage collection)回收。

因此使用闭包需要注意一下两点:

  1. 由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题。
  2. 不能随便改变上层函数(父函数)内部变量的值。 常见的几种写法:

1、给函数添加一些属性

function Circle(r) {
    this.r = r;
}
Circle.PI = 3.14159;
Circle.prototype.area = function() {
   return Circle.PI * this.r * this.r;
}
var c = new Circle(1.0);
alert(c.area()); //3.14159

2、声明一个变量,将一个函数当作值赋给变量

var Circle = function() {
    var obj = new Object();
    obj.PI = 3.14159;
          obj.area = function( r ) {
        return this.PI * r * r;
    }
    return obj;
}
var c = new Circle();
alert( c.area( 1.0 ) ); //3.14159

3、这种方法使用较多,也最为方便。var obj = {}就是声明一个空的对象

var Circle={
    "PI":3.14159,
    "area":function(r){
        return this.PI * r * r;
    }
};
alert( Circle.area(1.0) );//3.14159

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏IT派

Java面试中常被问到的几大技术难题

大家在平常面试java的过程中都会遇到哪些难题呢?还有一些即将去面试java的童鞋们,你们想知道技术面试中会涉及到哪些点吗?达妹为你整理Java面试中会被问到的...

12400
来自专栏HappenLee的技术杂谈

C++雾中风景3:const用法的小结

const关键字,翻译成中文是常量,常数的意思。所以在绝大多数场合之中,const是来定义常量的,定义常量也是好的编程习惯。在C类语言之中,定义常量通常会使用宏...

12830
来自专栏码云1024

JAVA 面试基础

31470
来自专栏猿人谷

C++重要知识点小结---3

C++重要知识点小结---1:http://www.cnblogs.com/heyonggang/p/3246631.html C++重要知识点小结---2:h...

17860
来自专栏数据处理

python命名中下划线的含义

19720
来自专栏老九学堂

最新Java高薪面试题+答案+解析!

今天老九君给大家分享一些Java面试需要的题目哟~ 01 anonymousinnerclass(匿名内部类)是否可以extends(继承)其它类,是否可以im...

46370
来自专栏深度学习自然语言处理

Python学习——collections系列

一 ,计数器(counter) Counter是对字典类型的补充,用于追踪值得出现次数 ps:具备字典的所有功能 + 自己的功能 例: >>> from ...

368140
来自专栏个人随笔

房上的猫:类的无参方法

一.类的无参方法  1.概述:   (1)类是由一组具有相同属性和共同行为的实体抽象而来的   (2)对象执行的操作是通过编写类的方法实现的   (3)类的每一...

386130
来自专栏Kevin-ZhangCG

[ Java面试题 ]基础篇之一

22050
来自专栏从流域到海域

《笨办法学Python》 第6课手记

《笨办法学Python》 第6课手记 第6课讲字符串和文本,作者给出的代码如下: x = "There are %d types of people." % 1...

20550

扫码关注云+社区

领取腾讯云代金券