2012-02-09 3 views
5

EDITJavascript закрытия - в чем разница между этими

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

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

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

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" 

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

Итак, как, в чем разница?

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

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

ответ

3

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

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

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; 
})(); 
+0

это гораздо лучший ответ, чем раньше. И да, я понимаю, что я устанавливаю объект как результат непосредственно выполняемой функции, а не устанавливая свойство указанного объекта. Предположим, я пытаюсь сделать только «print_me», который будет единственным свойством на тестовый объект. Каковы преимущества этого в закрытии, а не как прямое назначение? – tkone

+0

@tkone: Преимущество делать это в закрытии - это просто, что у вас есть закрытие. Вы можете создавать локальные переменные, чтобы не загрязнять глобальное пространство имен. Однако быть осторожным с глобальным пространством имен является проблемой, если вы пишете библиотечный код или плагины. Например, большая библиотека jQuery добавляет только два имени в глобальное пространство имен. – Guffa

+0

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

2

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

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

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

+1

Я действительно хочу Javascript было лучшим способом сделать личные вещи частными ... –

+1

«никоим образом» не является не совсем правильно. Некоторые (старые) js-движки позволяют получить доступ к атрибуту '.__ parent__' функций, которые могут иметь доступ к закрытой родительской области. – jAndy

+0

@ JanKuča Я понимаю проблемы, связанные с этим вопросом - то, что я прошу, не имеет ничего общего с частным/общественным или эмулятором, но разница между двумя примерами - одна в закрытии, экспортирующая ВСЕ, и одна за пределами закрытия , – tkone

0

Первый метод вы настоящий (анонимная функция, которая выполняется немедленно) не позволяет вашей программе выйти из глобальной области. В этой частной сфере вы можете решить, какие свойства вы хотите, чтобы выставить в качестве 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 
Смежные вопросы