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

!function () {}();

10 ответов

Решение

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

function foo() {}

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

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

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

Так что автор делает сохранение байта для выражения функции; более читабельный способ написать это будет так:

(function(){})();

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

Функция:

function () {}

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

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

function () {}()

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

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

!function () {}()

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

(function () {})()

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

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

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

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

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

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

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

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

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

function () { return false; }();  // syntax error

Это просто, чтобы сохранить байт данных, когда мы делаем минификацию javascript.

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

function (){}

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

(function (){}())

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

!function (){}()

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

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

Для последнего один из синтаксисов:

( function my_function() {} )()

Мы можем сделать что-то вроде:

(function add_them(a,b) { return a+b;} )(9,4)

Как и одновременное определение функции и вызов.

Редактировать:
Теперь вы спросите, что толку от "!" определение функции типа. Давайте рассмотрим следующее:

!function a_would_be_function() { alert("Do some junk but inside a function"); }()

Вы хотели бы выполнить функцию, как указано выше, но без '!' сгенерирует ошибку. Надеюсь, я в порядке.

Это еще один способ написания IIFE (выражение, вызываемое немедленно).

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

(function( args ) {})()

такой же как

!function ( args ) {}();

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

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

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

// I'm going to leave the closing () in all examples as invoking the function with just ! and () takes away from what's 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

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

var boy = true;
undefined
boy
true
!boy
false

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

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

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

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

(() => {})()

пример:

(() => {return "yeah"})()

! Символ показывает, что это выражение, вызываемое немедленно.

Восклицательный знак не будет вызывать функцию в одиночку; Вы можете поставить () в конце:

!function foo() {}()
() has higher precedence than ! and instantly calls the function.
() имеет более высокий приоритет, чем! и мгновенно вызывает функцию.

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

(function(){})();

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

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