2015-01-19 2 views
0

Рассмотрим следующие две функции,Почему (function() {...}()) создает состояние «singleton»?

// 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! Мозг!" момент на этот момент об этом, но я не понимаю, почему 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 

ответ

2

Тривиально, ваш номер returnImmediatelyExecutedFunction является ссылкой на номер одного вызова прилагаемого состояния, поэтому каждое использование этой ссылки будет иметь доступ к тому же состоянию.

В противном случае каждый звонок до returnObject выполняет новый вызов возвращенной функции и ее закрытого состояния.

Обратите внимание, что ваш returnImmediatelyExecutedFunction также семантически эквивалентно:

var returnImmediatelyExecutedFunction = returnObject(); 

т.е. это просто сам экземпляр. Поэтому, учитывая:

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

Следует заметить, что тривиальный summer1 и summer2 являются тем же экземпляром.

1

Это может быть легче увидеть на anotating, где объекты/прицелы создаются и используются:

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*/ 
1

В обоих случаях у вас есть функция, которая возвращает объект, когда вы его вызываете.

С returnImmediatelyExecutedFunction запустить функцию один раз (создавая один объект), а затем вы делаете кучу разных вещей, чтобы объект (который не является функцией), в том числе копирование его из summer1 в summer2, что вы храните в returnImmediatelyExecutedFunction ,

С помощью функции returnObject вы запускаете функцию дважды и выполняете кучу разных вещей для двух разных объектов.

Смежные вопросы