重拾ECMAScript基础——闭包与匿名函数

ECMAScript中经常把闭包与匿名函数混用,所以很多时候会搞不清这两个概念

闭包是指有权访问另一个函数作用域中的变量的函数。——《JS高程》

Closures (闭包)是使用被作用域封闭的变量,函数,闭包等执行的一个函数的作用域。通常我们用和其相应的函数来指代这些作用域。(可以访问独立数据的函数)
闭包是一个函数和声明该函数的词法环境的组合。从理论角度来说,所有函数都是闭包。
——MDN https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures

函数表达式

JavaScript中声明函数有两种方式

// 1.函数声明
function functionName(arg0, arg1, arg2) {
  //函数体
}
// 2.匿名函数赋值
var functionName = function(arg0, arg1, arg2){
  //函数体
}

作用域链

在函数执行过程中,需要在作用域链中查找变量:

function compare(value1, value2){
   if (value1 < value2){
     return -1;
   } else if (value1 > value2){
     return 1;
   } else {
     return 0;
   }
}
var result = compare(5, 10); 
作用域链.png

当函数执行完毕后,局部活动对象就会被销毁,内存中仅保存全局作用域(全局执行环境的变量对象);

闭包

而闭包有所不同

闭包是一种特殊的对象。它由两部分构成:函数,以及创建该函数的环境。环境由闭包创建时在作用域中的任何局部变量组成。

function createComparisonFunction(propertyName) {

   return function(object1, object2){
     var value1 = object1[propertyName];
     var value2 = object2[propertyName];

     if (value1 < value2){
       return -1;
     } else if (value1 > value2){
       return 1;
     } else {
       return 0;
     }
   };
 } 

var compare = createComparisonFunction("name");
var result = compare({ name: "Nicholas" }, { name: "Greg" }); 

createComparisonFunction这个函数中,返回的匿名函数赋值给了compare这个变量,我们可以说compare是一个闭包
返回的匿名函数的作用域链中可以访问在createComparisonFunction中的所有变量,而且函数在执行完毕后,其活动对象也不会被销毁,因为匿名函数的作用域链仍然在引用这个活动对象。
直到匿名函数被销毁后,createComparisonFunction()的活动对象才会被销毁;

//创建函数
var compareNames = createComparisonFunction("name");
//调用函数
var result = compareNames({ name: "Nicholas" }, { name: "Greg" });
//解除对匿名函数的引用(以便释放内存)
compareNames = null; 

首先,创建的比较函数被保存在变量compareNames 中。而通过将compareNames 设置为等于null
解除该函数的引用,就等于通知垃圾回收例程将其清除。随着匿名函数的作用域链被销毁,其他作用域
(除了全局作用域)也都可以安全地销毁了。


作用域链.png

闭包与匿名函数

在开发中,我们常会用到这样的写法

(function () {
    // ... all vars and functions are in this scope only
    // still maintains access to all globals
}());

这里声明匿名函数立即执行,使得局部变量不会污染到全局变量,并可以访问全局变量(外部变量);

var num = 1;
(function () {
    var num = 2;
    console.log(num); // 2
}())
console.log(num); // 1

匿名函数通常与闭包一起使用,但并无必然联系;
因为闭包保存的是变量对象,所以我们往往要用匿名函数立即执行来保存过程中的值;(见需要注意)

闭包的实用

想了想,自己总结的不如直接看文档。
MDN 文档 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures

  1. 在函数中给事件驱动型的变量添加函数;
  2. 模拟私有方法

需要注意

作用域链的这种配置机制引出了一个值得注意的副作用,即闭包只能取得包含函数中任何变量的最后一个值。 ——《JS高程》

因为闭包所保存的是整个变量对象;

function createFunctions(){
   var result = new Array();
   for (var i=0; i < 10; i++){
   result[i] = function(){
       return i;
     };
   }
   return result;
} 

//都是10

我们必须通过匿名函数的立即执行来进行保存

function createFunctions(){
   var result = new Array();
   for (var i=0; i < 10; i++){
     result[i] = function(num){
       return function(){
         return num;
       };
     }(i);
   }
   return result;
} 

//1-10

当然,ES6可以使用let来替代

function createFunctions(){
   var result = new Array();
   for (let i=0; i < 10; i++){
   result[i] = function(){
       return i;
     };
   }
   return result;
} 
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容