Чем IIFE лучше объявления именованной функции для предотвращения конфликта имен?

Я прочитал в stackoverflow, что Преимущество шаблона IIFE при реализации модулей вместо простого «объявления именованной функции» заключается в том, что в больших проектах он может предотвратить конфликты имен. Однако мне кажется, что IIFE не лучше и не хуже, чем объявление именованной функции для предотвращения конфликта имен.

Рассмотрим 2 метода написания библиотеки, которая предоставляет имя «GenericModuleName»:

Подход IIFE

var GenericModuleName = (function () {
    return ObjectWhichHasPublicMethod;
})();

Подход к объявлению именованных функций

function GenericModuleName() {
    return {
        PublicMethod : function () { privateMethod(); }
    }
};

В обоих случаях, если пользователь библиотеки по совпадению также имеет функцию с именем GenericModuleName, все равно будет конфликт имен, не так ли? Так чем же IIFE лучше «объявления именованной функции» для предотвращения конфликта имен?


person moog    schedule 01.08.2016    source источник
comment
Вопрос, на который вы ссылаетесь, не дает имени IIFE, он использует анонимную функцию. Нет конфликта имен, потому что нет имени.   -  person Barmar    schedule 01.08.2016
comment
Вы ничего не можете сделать, чтобы предотвратить конфликты, если две библиотеки имеют одинаковое имя для самого модуля. Идея состоит в том, чтобы предотвратить конфликты между функциями в разных модулях.   -  person Barmar    schedule 01.08.2016
comment
@Barmar В реальной жизни разве IIFE не будет назван для того, чтобы его можно было вызвать?   -  person moog    schedule 01.08.2016
comment
Нет. Помещение () после определения вызывает его немедленно. Вот почему это называется выражением функции с немедленным вызовом.   -  person Barmar    schedule 01.08.2016
comment
Я не понимаю Предотвратить конфликты между функциями в разных модулях. Я думал, что конфликты между функциями в разных модулях невозможны, потому что foo ModuleA никогда не будет конфликтовать с foo ModuleB, поскольку foo должен быть квалифицирован экземпляром ModuleA или ModuleB, например a.foo или b.foo?   -  person moog    schedule 01.08.2016
comment
Это моя точка зрения. Единственный конфликт, который вы получите, это если оба модуля называются ModuleA, так как это имя IIFE.   -  person Barmar    schedule 01.08.2016
comment
Бармар @Quentin Спасибо за оба ваших ответа. Оба ваших ответа (если я правильно понял) укрепляют мое мнение о том, что IIFE не более уступает/превосходит, чем объявление именованной функции с точки зрения инкапсуляции или предотвращения конфликта имен в большом проекте. (Пожалуйста, поправьте меня, если я неправильно понял.) Это заставляет меня задаться вопросом, почему IIFE является таким популярным объяснением того, как создавать модули Javascript ... нет никаких дополнительных преимуществ для многословия.   -  person moog    schedule 01.08.2016
comment
С чего вы взяли, что одно должно быть лучше другого? Вы даете ему имя, если вам нужно обратиться к нему позже (например, jQuery), вы не даете ему имя, если вам просто нужно вызвать его один раз для инициализации модуля.   -  person Barmar    schedule 01.08.2016


Ответы (1)


Ваши два примера на самом деле несопоставимы.

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

Фактическим эквивалентом будет:

var GenericModuleName = ObjectWhichHasPublicMethod;

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

var GenericModuleName = function() {

    var i = 0;

    function privateMethod() {
        return i++;
    }

    return {
        PublicMethod : function PublicMethod() { privateMethod(); }
    }
}();

Ни i, ни privateMethod не являются глобальными, поэтому они не могут конфликтовать с другими глобальными переменными.

person Quentin    schedule 01.08.2016