为什么(function(){...}())创建“单例”状态?

时间:2015-01-19 10:40:00

标签: javascript

考虑以下两个功能,

// function 
var returnObject = function() { 
  var values = []; 

  return {
    sum: function(addend) { 
      var toReturn = 0;
      if (addend) {
        values.push(addend);
      }
      values.forEach(function(el) {
        toReturn += el; 
      });
      return toReturn;
    }
  }
};  

// immediately executed function 
var returnImmediatelyExecutedFunction = (function() { 
  var values = []; 

  return {
    sum: function(addend) { 
      var toReturn = 0;
      if (addend) {
        values.push(addend);
      }
      values.forEach(function(el) {
        toReturn += el; 
      });
      return toReturn;
    }
  }
}()); 

我有一个" eeeergh!脑&#34!;关于这一点的时刻,但我不明白为什么returnObject每次使用时都返回一个唯一的闭包状态,但returnImmediatelyExecutedFunction返回相同的状态。

考虑以下内容的输出:

var summer1 = returnImmediatelyExecutedFunction; 
summer1.sum(2); 
summer1.sum(4); 
summer1.sum(8);
console.log(summer1.sum()); 

var summer2 = returnImmediatelyExecutedFunction; 
summer2.sum(2); 
summer2.sum(4); 
summer2.sum(8);
console.log(summer2.sum()); 

var summer3 = returnObject(); 
summer3.sum(2); 
summer3.sum(4); 
summer3.sum(8);
console.log(summer3.sum());

var summer4 = returnObject(); 
summer4.sum(2); 
summer4.sum(4); 
summer4.sum(8);
console.log(summer4.sum());

输出:

14
28 // why not 14? 
14 
14

3 个答案:

答案 0 :(得分:2)

通常,您的returnImmediatelyExecutedFunction是对封闭状态的单一调用的引用,因此每次使用该引用都将访问相同的状态。

否则,每次调用returnObject都会对返回的函数及其封闭状态进行新的调用。

请注意,您的returnImmediatelyExecutedFunction在语义上也等同于:

var returnImmediatelyExecutedFunction = returnObject();

即。它只是一个实例本身。所以给出:

var summer1 = returnImmediatelyExecutedFunction;
var summer2 = returnImmediatelyExecutedFunction;
var summer3 = returnObject();
var summer4 = returnObject();

应该轻而易举地指出summer1summer2 是同一个实例

答案 1 :(得分:1)

通过注释创建和使用对象/范围的位置可能更容易看到:

returnObject = ... /* No scope created, just a function is given a name */
returnImmediatelyExecutedFunction = ... /* Create scope A */

var summer1 = returnImmediatelyExecutedFunction;  /*A*/
summer1.sum(2); /*A*/
summer1.sum(4); /*A*/
summer1.sum(8); /*A*/
console.log(summer1.sum()); /*A*/

var summer2 = returnImmediatelyExecutedFunction; /*Still A*/
summer2.sum(2); /*Still A*/
summer2.sum(4); /*Still A*/
summer2.sum(8);/*Still A*/
console.log(summer2.sum()); /*Still A*/

var summer3 = returnObject(); /* Create scope B */
summer3.sum(2); /*B*/
summer3.sum(4); /*B*/
summer3.sum(8); /*B*/
console.log(summer3.sum()); /*B*/

var summer4 = returnObject(); /* Create scope C */
summer4.sum(2); /*C*/
summer4.sum(4); /*C*/
summer4.sum(8); /*C*/
console.log(summer4.sum()); /*C*/

答案 2 :(得分:1)

在这两种情况下,你都有一个函数在你调用它时返回一个对象。

使用returnImmediatelyExecutedFunction运行一次函数(创建一个对象),然后对对象执行一系列不同的操作(这不是函数),包括从summer1复制它到summer2returnImmediatelyExecutedFunction

使用returnObject,您可以运行该函数两次,并为两个不同的对象执行一些不同的操作。