Javascript замыкания - в чем разница между этими - PullRequest
5 голосов
/ 09 февраля 2012

РЕДАКТИРОВАТЬ

С количеством ответов, говорящих "вы можете делать личные вещи!"ниже, я собираюсь добавить это также к вершине:

Я знаю, что вы можете эмулировать закрытые переменные внутри замыкания.Это не то, что я спрашиваю.Я спрашиваю, учитывая два приведенных ниже примера, где я «экспортирую» ВСЕ из замыкания, какова принципиальная разница между этими двумя примерами.

Учитывая эти два метода создания объектов / методов:

var test = {}

test = (function(){
    var a_method = function(print_me){
        return "hello "+print_me;
    }

    return {print_me: a_method};
})();

test.print_me2 = function(print_me2){
   return "hello "+print_me2;
}

test.print_me('world');
>>> returns "hello world"

test.print_me2('world');
>>> returns "hello world"

Я понимаю, что первый метод позволяет использовать закрытые переменные (которые я, как разработчик Python, не очень люблю использовать), но оба мне кажутся довольно эквивалентными, только первыйвыглядит «круче» (как и во всех больших javascript-программах, кажется, что люди так делают), а второй способ выглядит очень пассивно.

Итак, какая разница?

IЗдесь вы просмотрели закрывающие вопросы - большинство из них сосредоточены вокруг того, что или почему вы их используете;Я понимаю их полезность, я просто хочу знать, почему вы делаете первое по сравнению со вторым и какие у него есть преимущества.

Я бы предпочел неопровержимые доказательства, а не догадки - не искать "вот каккрутые дети делают это "или" я слышал, что mozilla лучше использует память, когда вы используете замыкание ", но это скорее качественное свидетельство того, что одно из них" лучше ", чем другое.

Ответы [ 3 ]

3 голосов
/ 09 февраля 2012

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

Существуют разныеспособы добавления методов к объекту.Вы можете поместить их туда при создании объекта:

var test = {
  print_me: function(text) { return "hello " + text; }
};

Вы можете добавить метод в качестве свойства к существующему объекту:

var test = {};
test.print_me = function(text) { return "hello " + text; };

Вы можете создать функцию конструктора, идобавьте методы к его прототипу:

function Test() {}
Test.prototype.print_me = function(text) { return "hello " + text; };
var test = new Test();

Поскольку у Javascript есть объектная модель на основе прототипа, последний способ - это то, как методы были предназначены для создания.Другие способы просто возможны, потому что свойство объекта может иметь функцию в качестве значения.


Вы можете использовать функцию-оболочку для любого кода, где вам нужны локальные переменные, так что вы можете сделать это вторым способом.установки свойства:

test.print_me2 = (function(){

  var method = function(print_me2) {
    return "hello "+print_me2;
  }

  return method;
})();
2 голосов
/ 09 февраля 2012

В первом примере замыкание используется для того, чтобы локальные переменные не попадали в глобальную область.

var thisIsGlobal = 2;
var test = (function () {
  var thisIsLocal = 3;
  return function () {
    return thisIsLocal;
  };
}());

Получается функция test, которая при вызове возвращает значение локальной переменной thisIsLocal. Нет возможности изменить значение переменной. Вы можете посмотреть на это как на приватную переменную.

0 голосов
/ 09 февраля 2012

Первый метод, который вы предоставляете (анонимная функция, которая выполняется немедленно), удерживает вашу программу вне глобальной области видимости. В этой частной области вы можете решить, какие свойства вы хотите использовать в качестве своего API:

(function(win){
  var a, b, c = 1;  

  function init(){ 
    return aa(b);
  }

  function exit(){
    if(cc()){
      return a;
    }
  }

  function aa(){
  }

  function bb(){
  }

  function cc(){
  }

  win.myProgram = {init: init,
                   exit: exit };
})(window);


// We now have access to your API from within the global namespace:    
myProgram.init();    
//etc
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...