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

1089
!function () {}();
Показать ещё 2 комментария
Теги:
function

10 ответов

1928
Лучший ответ

Синтаксис JavaScript 101. Вот объявление функции:

function foo() {}

Обратите внимание, что нет точки с запятой: это просто функция Объявление. Вам понадобится вызов foo(), чтобы запустить функцию.

Теперь, когда мы добавляем, казалось бы, безобидный восклицательный знак: !function foo() {} он превращает его в выражение . Теперь это выражение функции.

Только ! не вызывает функцию, но мы можем теперь положить () в конец: !function foo() {}(), который имеет более высокий приоритет, чем !, и мгновенно вызывает функцию.

Итак, что делает автор, это сохранение байта на выражение функции; более читаемым способом написания будет следующее:

(function(){})();

Наконец, ! делает выражение return true. Это связано с тем, что по умолчанию все IIFE возвращают undefined, что оставляет нас с !undefined, который равен true. Не особенно полезно.

  • 214
    +1. Это действительно лучший ответ здесь, и, к сожалению, вряд ли проголосовали. Очевидно ! возвращает логическое значение, мы все это знаем, но вы замечаете, что он также преобразует оператор объявления функции в выражение функции, чтобы можно было немедленно вызывать функцию, не заключая ее в скобки. Не очевидно, а ясно намерение кодера.
  • 54
    +1 Это единственный ответ, который на самом деле касается того, ПОЧЕМУ вы хотели бы сделать это, и почему кто-то видит, что он использовал больше, чем могло показаться оправданным отрицанием результата возврата. Одинарный оператор! (также ~, - и +) устраняет неоднозначность из объявления функции и позволяет пареням в конце () вызывать функцию на месте. Это часто делается для создания локальной области видимости / пространства имен для переменных при написании модульного кода.
Показать ещё 14 комментариев
346

Функция:

function () {}

ничего не возвращает (или undefined).

Иногда мы хотим вызвать функцию справа, когда мы ее создаем. У вас может возникнуть соблазн попробовать следующее:

function () {}()

но это приводит к SyntaxError.

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

!function () {}()

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

(function () {})()
  • 24
    кому это может понадобиться?
  • 13
    это единственный ответ, который объясняет случай в вопросе, браво!
Показать ещё 9 комментариев
53

Существует хорошая точка для использования ! для вызова функции, помеченного на airbnb JavaScript guide

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

!function abc(){}()
!function bca(){}();

Будет работать так же, как

!function abc(){}()
;(function bca(){})();

но сохраняет два символа и выглядит лучше.

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

abcval = !function abc(){return true;}() // abcval equals false
bcaval = +function bca(){return true;}() // bcaval equals 1
zyxval = -function zyx(){return true;}() // zyxval equals -1
xyzval = ~function xyz(){return true;}() // your guess?

но если вы используете шаблоны IIFE для одного файла, разделите код модуля и используйте инструмент concat для оптимизации (что делает однострочное однострочное задание), чем конструкция

!function abc(/*no returns*/) {}()
+function bca() {/*no returns*/}()

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

Это вызовет ошибку JavaScript. ASI не сможет выполнить свою работу.

!function abc(/*no returns*/) {}()
(function bca() {/*no returns*/})()

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

Это работает:

!function abc(/*no returns*/) {}()
^function bca() {/*no returns*/}()

Это не:

^function abc(/*no returns*/) {}()
!function bca() {/*no returns*/}()
  • 3
    На самом деле, эти другие символы не имеют того же эффекта. Да, они позволяют вам вызывать функцию, как описано, но они не идентичны. Обратите внимание: var foo =! Function (bar) {console.debug (bar); }("летучая мышь"); Независимо от того, какой из ваших символов вы ставите перед собой, вы получаете «летучую мышь» в консоли. Теперь добавьте console.debug ("foo:", foo); - вы получите очень разные результаты в зависимости от того, какой символ вы используете. ! вызывает возвращаемое значение, которое не всегда желательно. Я предпочитаю синтаксис ({}) () для ясности и точности.
27

Возвращает, может ли оператор оценивать значение false. например:

!false      // true
!true       // false
!isValid()  // is not valid

Вы можете использовать его дважды, чтобы принудительно использовать значение для boolean:

!!1    // true
!!0    // false

Итак, чтобы более точно ответить на ваш вопрос:

var myVar = !function(){ return false; }();  // myVar contains true

Изменить: У этого есть побочный эффект изменения объявления функции на выражение функции. Например. следующий код недействителен, поскольку он интерпретируется как объявление функции, в котором отсутствует требуемый идентификатор (или имя функции):

function () { return false; }();  // syntax error
  • 6
    Для ясности для читателей, которые могут захотеть использовать назначение с немедленно вызванной функцией, ваш пример кода var myVar = !function(){ return false; }() может опустить ! like var myVar = function(){ return false; }() и функция будет выполнена правильно, а возвращаемое значение останется нетронутым.
  • 1
    Чтобы быть понятным, вы можете использовать его один раз, чтобы привести к логическому, потому что это логический не оператор. ! 0 = истина и! 1 = ложь. В целях минимизации JavaScript вы бы хотели заменить true на !0 и false на !1 . Сохраняет 2 или 3 символа.
5

Только для сохранения байта данных при миниатюризации javascript.

рассмотрим анонимную функцию ниже

function (){}

Чтобы сделать вышеприведенную функцию self invoking, мы обычно изменим приведенный выше код как

(function (){}())

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

!function (){}()

Тем не менее, оба являются функциями self invoking, и мы также сохраняем байт. Вместо двух символов (,) мы использовали только один символ !

  • 0
    Это полезно, потому что часто вы увидите это в минимизированном JS
5

! является логическим оператором НЕ, это логический оператор, который будет инвертировать что-то в свою противоположность.

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

Вместо этого используйте закрывающую скобку и BANG (!), если это необходимо.

// I'm going to leave the closing () in all examples as invoking the function with just ! and () takes away from what happening.

(function(){ return false; }());
=> false

!(function(){ return false; }());
=> true

!!(function(){ return false; }());
=> false

!!!(function(){ return false; }());
=> true

Другие операторы, которые работают...

+(function(){ return false; }());
=> 0

-(function(){ return false; }());
=> -0

~(function(){ return false; }());
=> -1

Комбинированные операторы...

+!(function(){ return false; }());
=> 1

-!(function(){ return false; }());
=> -1

!+(function(){ return false; }());
=> true

!-(function(){ return false; }());
=> true

~!(function(){ return false; }());
=> -2

~!!(function(){ return false; }());
=> -1

+~(function(){ return false; }());
+> -1
5

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

!function bool() { return false; }() // true
!function bool() { return true; }() // false

Опуская ! в приведенных выше примерах будет SyntaxError.

function bool() { return true; }() // SyntaxError

Тем не менее, лучший способ достичь этого:

(function bool() { return true; })() // true
2

Еще один способ записи IIFE (непосредственное выражение функции).

Другой способ написания -

(function( args ) {})()

то же, что и

!function ( args ) {}();
  • 0
    Ну, это не совсем то же самое; 2-ая форма отрицает результат вызова функции (и затем выбрасывает его, потому что нет никакого назначения значения). Я бы строго предпочел более явный синтаксис (function (args) {...})() и оставил бы эту !function форму инструментам минимизации и запутывания.
0

Позвольте сохранить несколько других байтов!

(() => {})()

пример:

(() => {return "yeah"})()
  • 2
    (() => 'yeah')();
  • 0
    Ага. даже лучше.
0

! будет отрицать (наоборот) то, что вы ожидаете в результате, т.е. если у вас

var boy = true;
undefined
boy
true
!boy
false

когда вы вызываете boy, ваш результат будет true, но как только вы добавите ! при вызове boy, i.e !boy, ваш результат будет false. Другими словами, вы имеете в виду NotBoy, но на этот раз это в основном логический результат: true или false.

То же самое, что происходит с выражением !function () {}();, и только function () {}(); укажет вам ошибку, но добавит ! прямо перед вашим выражением function () {}();, делает его противоположным function () {}(); > который должен вернуть вас true. Пример можно увидеть ниже:

function () {}();
SyntaxError: function statement requires a name
!function () {}();
true

Ещё вопросы

Сообщество Overcoder
Наверх
Меню