В чем преимущество JavaScript! (){}() Перед (function () {})() в JavaScript?

Возможный дубликат:
Что делает восклицательный знак перед функцией?

Я давно использовал следующие функции для самостоятельного выполнения анонимных функций в JavaScript:

(function () { /* magic happens */ })()

В последнее время я начал видеть больше экземпляров следующего шаблона (например, в Bootstrap):

!function () { /* presumably the same magic happens */ }()

Кто-нибудь знает, в чем преимущество второго паттерна? Или это просто стилистическое предпочтение?

6 ответов

Решение

Эти два различных метода имеют функциональное различие, а также различие во внешнем виде. Потенциальные преимущества одного метода над другим будут обусловлены этими различиями.

краткость

Javascript - это язык, где краткость может быть очень важной, потому что Javascript загружается при загрузке страницы. Это означает, что чем лаконичнее Javascript, тем быстрее время загрузки. По этой причине существуют минифайеры и обфускаторы Javascript, которые сжимают файлы Javascript для оптимизации времени загрузки. Например, пробелы в alert ( "Hi" ) ; будет оптимизирован для alert("Hi");,

Имея это в виду, сравните эти две модели

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

Отрицание возвращаемого значения

Сравните результат значение a а также b,

var a = (function(){})()
var b = !function(){}()

Так как a функция ничего не возвращает, a будет undefined, Поскольку отрицание undefined является true, b будет оценивать true, Это преимущество для людей, которые либо хотят отрицать возвращаемое значение функции, либо имеют фетиш "все, что нужно вернуть, не ноль или не определено значение". Вы можете увидеть объяснение того, как это работает с другим вопросом переполнения стека.

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

Я всегда возвращаюсь к пьесе Бена Алмана IIFE по таким вопросам. Это определенно, насколько я понимаю.

Вот мясо статьи:

// Either of the following two patterns can be used to immediately invoke
// a function expression, utilizing the function's execution context to
// create "privacy."

(function(){ /* code */ }()); // Crockford recommends this one
(function(){ /* code */ })(); // But this one works just as well

// Because the point of the parens or coercing operators is to disambiguate
// between function expressions and function declarations, they can be
// omitted when the parser already expects an expression (but please see the
// "important note" below).

var i = function(){ return 10; }();
true && function(){ /* code */ }();
0, function(){ /* code */ }();

// If you don't care about the return value, or the possibility of making
// your code slightly harder to read, you can save a byte by just prefixing
// the function with a unary operator.

!function(){ /* code */ }();
~function(){ /* code */ }();
-function(){ /* code */ }();
+function(){ /* code */ }();

// Here's another variation, from @kuvos - I'm not sure of the performance
// implications, if any, of using the `new` keyword, but it works.
// http://twitter.com/kuvos/status/18209252090847232

new function(){ /* code */ }
new function(){ /* code */ }() // Only need parens if passing arguments

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

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

(function(){ /* ... */ })(); // Arguably most common form, => undefined
(function(){ /* ... */ }()); // Crockford-approved version, => undefined
!function(){ /* ... */ }();  // Negates the return, so => true
+function(){ /* ... */ }();  // Attempts numeric conversion of undefined, => NaN
~function(){ /* ... */ }();  // Bitwise NOT, => -1

Если вы не фиксируете возвращаемое значение, нет существенной разницы. Можно утверждать, что ~ может быть более быстрой операцией, поскольку она просто переворачивает биты, или, может быть! это более быстрая операция, так как это проверка на истинность / ложность и возвращение отрицания.

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

У Бена Алмана фантастическая рецензия на эту тему: http://benalman.com/news/2010/11/immediately-invoked-function-expression/

Первый "шаблон" вызывает анонимную функцию (и имеет результат ее возвращаемого значения), а второй вызывает анонимную функцию и отрицает ее результат.

Это то, что вы спрашиваете? Они не делают то же самое.

Это почти единственное стилистическое предпочтение, за исключением того факта, что ! обеспечивает возврат функции (т.е. возвращает true, который исходит от !undefined).

Кроме того, это на один персонаж меньше.

Ну, в первом случае вы используете ( ) обернуть объект, который вы хотите выполнить, со следующим набором (), а в следующем случае вы используете оператор, который принимает один аргумент (оператор отрицания!), и вы заставляете его неявно оборачивать свой аргумент (функцию) с помощью ( ) так что вы на самом деле получаете !(function () { })(), выполните функцию и отмените результат, который она возвращает. Это также может работать с -, +, ~ по тому же принципу, поскольку все эти операторы принимают один аргумент.

!function () { /* presumably the same magic happens */ }()
-function () { /* presumably the same magic happens */ }()
+function () { /* presumably the same magic happens */ }()
~function () { /* presumably the same magic happens */ }()

Зачем тебе это делать? Я думаю, это личное предпочтение или если у вас большой.JS и вы хотите сохранить 1 символ на анонимный вызов функции...:D

Другие вопросы по тегам