美文网首页
重拾ECMAScript基础——闭包与匿名函数

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

作者: JacobMa1996 | 来源:发表于2018-01-16 18:35 被阅读0次

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;
} 

相关文章

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

    ECMAScript中经常把闭包与匿名函数混用,所以很多时候会搞不清这两个概念 闭包是指有权访问另一个函数作用域中...

  • 后端程序员的 JavaScript 之旅 - 模块化(一)

    基础模式 匿名闭包 匿名闭包是很常用的代码隔离方式,声明匿名对象并立即执行。匿名函数中声明的变量和方法以及匿名函数...

  • 闭包

    闭包 闭包和函数的区别:闭包可以储存一部分变量,函数不能,函数传什么有什么值 函数与匿名函数的区别,匿名函数可以完...

  • 理解javascript(匿名函数和闭包)这篇文章就够了

    匿名函数就是没有名字的函数,闭包是可访问一个函数作用域里变量的函数。 一.匿名函数 二:闭包 闭包的概念:闭包是指...

  • golang关于defer的问题

    要弄明白defer首先得搞清楚闭包和局部作用域。 闭包 闭包是匿名函数与匿名函数所引用环境的组合。看一个例子: 看...

  • python 基础 06 匿名函数,闭包和重要的内置函数

    python 基础 06 1.匿名函数 匿名函数也叫一句话函数。基础就是列表推导式。 2. 闭包 3. 重要的内置函数

  • 匿名函数与闭包

    转自匿名函数与闭包的区别 匿名函数没有函数名称的函数; 闭包一个可以使用另外一个函数作用域中的变量的函数,或者说是...

  • php闭包函数(Closure)

    匿名函数 提到闭包就不得不想起匿名函数,也叫闭包函数(closures),貌似PHP闭包实现主要就是靠它。声明一个...

  • PHP闭包(Closure)初探

    匿名函数 提到闭包就不得不想起匿名函数,也叫闭包函数(closures),貌似PHP闭包实现主要就是靠它。声明一个...

  • [正儿八经PHP]PHP闭包(Closure)初探

    匿名函数 提到闭包就不得不想起匿名函数,也叫闭包函数(closures),貌似PHP闭包实现主要就是靠它。声明一个...

网友评论

      本文标题:重拾ECMAScript基础——闭包与匿名函数

      本文链接:https://www.haomeiwen.com/subject/vsfsoxtx.html