PhoneGap中文网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 830|回复: 0

JavaScript中闭包的本质

[复制链接]

87

主题

87

帖子

327

积分

中级会员

Rank: 3Rank: 3

积分
327
发表于 2017-8-27 22:42:57 | 显示全部楼层 |阅读模式
本帖最后由 w8484855@qq.com 于 2017-8-27 22:44 编辑

本文和大家分享的主要是javascript中闭包相关内容,一起来看看吧,希望对大家学习javascript有所帮助。
  闭包是JavaScript开发人员常常谈论的问题,大家普遍对闭包的认知如下:
  模糊的认知:闭包是定义在函数内部的函数;
  清晰的认知:闭包是会保存它引用到的外部变量的特殊函数;
其实在JavaScript语言中,以上2种认知都是错误的;为了帮助大家正确地认识闭包,现分享出我对闭包的研究和理解,如下:
  1. 闭包
  我对闭包的定义是:
  闭包的标准定义:携带外部变量的函数称为闭包;
  我之所以这样对闭包下定义,是因为这个定义几乎适用所有语言的闭包,如:Object-CSwiftJavaScript等等;所以我认为这是较标准的定义;
  对于JavaScript中的闭包虽然符合标准定义,但是由于JavaScript语言的一些特性,使得JavaScript中的闭包的实现与其它语言(如:Object-CSwift)的实现并不一样;
  很多人都认为闭包只会携带它内部引用的外部变量,并不会携带没有引用的外部变量,其实这是错误的;可以通过下面的代码证明:
  function outFun() {
  var outArg1 = "外部参数1";
  var outArg2 = "外部参数2";
  function outArg3() {
  console.log("外部参数3");
  }
  /*定义闭包
  * codeStr:字符串类型的参数,该参数的值将被当作代码执行
  * return : 返回将codeStr作为代码执行的结果;
  * */
  function closureFun(codeStr) {
  console.log("闭包引用的变量的值:",outArg1);
  return eval(codeStr);   //返回将codeStr作为代码执行的结果;
  }
  return closureFun;
  }
  var getValueOf  = outFun();     //获取闭包
  var arg2Value = getValueOf("outArg2");      //尝试获取闭包内没有引用的变量outArg2的值;console.log(arg2Value);     //输出结果为:外部参数2
  var arg3Value = getValueOf("outArg3");      //尝试获取闭包内没有引用的函数outArg3
  arg3Value();     //输出结果为:外部参数3
  从示例代码中的运行结果中可以看出,对于闭包引用到的外部变量outArg1 和 闭包没有引用到的变量outArg2和函数outArg3,在闭包执行时都能被正确地访问到,所以闭包会携带所有的外部变量(函数也是变量);
  为什么会这样呢?若要理解,还需先了解一下作用域链的知识,下面是我对JavaScript的作用域链的理解:
  2. 作用域链的理解
  1. 可以把作用域链理解成是一个栈结构;
  2. 每个作用域都有一个作用域对象用于保存在该作用域内创建的变量(包括函数),其保存的方式是:在作用域内创建的变量会成为作用域对象的属性;
  3. 作用链链保存的是各级作用域对象的引用,其中最近的作用域的作用域对象在最前端,越远的作用域的作用域对象越靠后;
  4. 全局作用域的作用域对象是全局对象本身;所以,每个作用域链的最后端都是全局对象的引用;
  5. 在全局作用域内创建的变量会成为全局对象的属性的原因:由于2(在作用域内创建的变量会成为作用域对象的属性)4(全局作用域的作用域对象是全局对象本身),所以在全局作用域创建的变量会成为全局对象的属性;
  6. 函数的作用域链是在函数对象被创建时(被定义时)创建的;
  7. 每当函数被执行时,都会新创建一个函数的作用域对象,并把该作用域对象推到作用域链的最前端;
  8. 第当函数执行结束时,都会把函数的作用域对象从该函数作用链中推出;
  3. 闭包的本质
  其实闭包携带外部变量的机制并非闭包的特有机制,它是函数的作用域链的一个效应;在JavaScript中,闭包和普通函数没有任何本质的区别,闭包只是函数在某种使用场景下的一个名字,就好比凶器只是刀在用于行凶时的名字;
  JavaScript中的闭包能携带外部变量的原因是:
  JavaScript的函数在被创建时(被定义时)会生成自己的作用域链;该作用域链会保存各级作用域对象的引用,所以JavaScript的函数能够访问其外部的所有变量;
  说见上文的< 作用域链的理解 >
  所以,本质上,JavaScript中的闭包携带的不是外部变量,而是外部的作用域对象;


来源:简书

it营
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

Archiver|手机版|小黑屋|PhoneGap中文网 ( 京ICP备13027796号-1

GMT+8, 2018-7-20 04:55 , Processed in 0.260965 second(s), 31 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表