JavaScript 闭包详细介绍

所属分类: 网络编程 / JavaScript 阅读数: 1181
收藏 0 赞 0 分享

深入理解JavaScript——闭包

  跟很多新手一样我也是初入前端,对闭包的理解花费的时间和精力相当的多。效果也还行,今天我就来根据自己的理解细致的讲一讲闭包,由于是初入学习的时候不免有一些弯路和困惑,我想信这也是很多跟我一样的人会同样遇到的问题。我就以自己的学习路径和遇到的各种坑来谈闭包。希望对各位有一定的帮助。(菜鸟,也请各位多多指教)

  闭包是什么?《JavaScript高级程序设计》上面这么描述的:闭包是指有权访问另一个函数作用域中的变量的函数。这句话第一次看的时候模模糊糊,似是而非。碰到问题就不会运用了,听别人的分析头头是道,说到底还是没搞明白。现在我觉得要彻底搞清这句话必须对JavaScript的作用域,匿名函数,甚至JavaScript的编译原理有一些简单的了解。经过查阅理解各种资料书籍对闭包的解释,再回过头来看了一些源码,慢慢的有了一点感觉。我觉得对闭包描述最好的一句话是:“闭包是基于词法作用域书写代码时所产生的自然结果,你甚至不需要为了利用它而有意为之的创建闭包,闭包的创建和使用是在你的代码中随处可见。你缺少的是根据你自己的意愿来识别,拥抱和影响闭包的思维环境。”话有点长但点出来闭包在JavaScript这么语言中存在的实际价值,大家可以细细体会一下。接下来我已实际例子来讲讲闭包。

首先看一个简单的例子:

function createComparisonFunction(propertyName){
  return function(obj1,obj2){
    var value1=object1[propertyName];
    var value2=object2[propertyName];
    if(value1<value2){
      return -1;
    }else if(value1>value2){
      return 1;
    }else{
      return 0;
    }
  } 
}

例子中返回的是一个匿名函数,其中匿名函数中value1,value2同时又对外部函数createComparisonFunction()的参数propertyName进行调用。再看看上面对闭包的定义:有权访问另一个函数作用域中的变量的函数。return的匿名函数有权访问外部函数作用域中的变量propertyName,因此这是一个闭包。但实际来说这只是一个基于词法作用域的查找规则,很好理解也很自然。

  可能有些人不明白什么是词法作用域的查找规则:其实说简单点就是根据变量的作用链域来查找并取得该变量。以上例来说:createComparisonFunction函数的作用域包含一个变量property和一个匿名函数(由于没有函数名其实在createComparisonFunction函数中也无法调用,这也是匿名函数的一个缺点,记得事件监听函数调用一个匿名函数时是无法移除吗?道理是一样的),匿名函数作用域中包括obj1,obj2,value1,value2这四个变量。匿名函数中的变量调用时首先在自己作用域中查询,找到了该变量就调用,找不到就往外层走接着找,直到全局作用域如果还是找不到就会报ReferenceError(如果找到了一个var a;呢?由于a为undefined所以会报TypeError)。而createComparisonFunction函数则只能在他的作用域中查找,不能去内层的匿名函数中查找,这种查找规则就是词法作用域的查找规则(当然这不只是基本规则)。

 我们再来看一个例子:

function foo() {
  var a = 2;
  function bar() {
    console.log( a );
  }
  return bar;
}
var baz = foo();
baz();  //2

  答案可能很多人都能猜出来但其实现原理是怎样呢?我现在就来细致的分析一下:首先声明了一个函数foo其作用域包括变量a和bar函数。foo函数内部有一个函数bar内部没有新变量。然后定义一个变量baz,其值为foo()而foo()返回bar,顾baz=bar;最后一句baz()即等价于bar();根据词法作用域的规则bar是在foo函数中声明的。外部是无法访问的呀!这正是闭包的神奇之处!我们再一次回到闭包定义:有权访问另一个函数作用域中的变量的函数,baz()函数有权访问foo函数中的bar。这就是闭包对吧!搞清闭包后有些人还会疑问?闭包是怎么形成的,为什么你说它有权访问foo中的bar呢?首先闭包的形成是在一个函数内部创建一个函数这是创建闭包的最常见方法。当将内部函数传递到它的词法作用域以外他都会持有对原始定义作用域的引用,执行此函数就会 使用闭包。

  闭包的基础大概就是这几点,希望大家能仔细体会。抽时间补充点闭包的一些其他用途,来帮大家扩展一下思维。

        通过此文,希望大家对闭包的知识掌握,谢谢大家对本站的支持!

更多精彩内容其他人还在看

Angular使用Md5加密的解决方法

这篇文章主要介绍了Angular使用Md5加密的解决方法,需要的朋友可以参考下
收藏 0 赞 0 分享

详解JS构造函数中this和return

本文通过实例代码给大家介绍了JS构造函数中this和return,需要的朋友参考下吧
收藏 0 赞 0 分享

ES6中Array.find()和findIndex()函数的用法详解

ES6为Array增加了find(),findIndex函数。find()函数用来查找目标元素,找到就返回该元素,找不到返回undefined,而findIndex()函数也是查找目标元素,找到就返回元素的位置,找不到就返回-1。下面通过实例详解,需要的朋友参考下吧
收藏 0 赞 0 分享

JS闭包的几种常见形式实例详解

本文通过实例代码给大家详细介绍了js闭包的几种常见形式,代码简单易懂,非常不错,具有参考借鉴价值,需要的朋友参考下
收藏 0 赞 0 分享

ES6中Array.copyWithin()函数的用法实例详解

ES6为Array增加了copyWithin函数,用于操作当前数组自身,用来把某些个位置的元素复制并覆盖到其他位置上去。下面重点给大家介绍ES6中Array.copyWithin()函数的用法,需要的朋友参考下
收藏 0 赞 0 分享

Javascript 严格模式use strict详解

严格模式:由ECMA-262规范定义的JavaScript标准,对javascrip的限制更强。这篇文章主要介绍了Javascript 严格模式use strict详解 ,需要的朋友可以参考下
收藏 0 赞 0 分享

引入JavaScript时alert弹出框显示中文乱码问题

今天在HTML中引入JavaScript文件运行时,alert弹出的提示框中文显示为乱码,怎么解决此问题呢?下面小编给大家带来了引入JavaScript时alert弹出框显示中文乱码问题的解决方法,一起看看吧
收藏 0 赞 0 分享

AngularJs 延时器、计时器实例代码

这篇文章主要介绍了AngularJs 延时器、计时器实例代码,需要的朋友可以参考下
收藏 0 赞 0 分享

JS分页的实现(同步与异步)

这篇文章主要介绍了JS分页的实现(同步与异步),需要的朋友可以参考下
收藏 0 赞 0 分享

Angularjs自定义指令实现分页插件(DEMO)

由于最近的一个项目使用的是angularjs1.0的版本,涉及到分页查询数据的功能,后来自己就用自定义指令实现了该功能,下面小编把实例demo分享到脚本之家平台,需要的朋友参考下
收藏 0 赞 0 分享
查看更多