Сразу же вызывается выражение функции без использования оператора группировки - PullRequest
24 голосов
/ 13 мая 2019

Я пытаюсь немедленно вызвать функцию без использования шаблона IIFE (заключив определение функции в круглые скобки).Здесь я вижу два сценария:

  1. Когда объявление функции вызывается немедленно: дает SyntaxError.

  2. Когда выражение функции вызывается немедленно: успешно выполняется .

Пример 1: даетSyntaxError

//gives `SyntaxError`
function() {
    console.log('Inside the function');
}();

Пример 2: Выполняется без ошибок

// Executes without any error
var x = function() {console.log('Inside the function')}(); // Inside the function

Итак, у меня есть следующие сомнения:

  • При таком подходе, почему он выдает ошибку для объявления функции но не для выражения функции ?
  • Есть ли способ немедленно вызвать объявление функции без использования шаблона IIFE ?

Ответы [ 6 ]

16 голосов
/ 13 мая 2019

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

function func(){
  console.log('x')
}();

Причина в том, что объявление функции не возвращает значения функции, однако, когда вы оборачиваете объявление функции внутри (), оно заставляет его быть выражением функции, которое возвращает значение.

Во втором примере function() {console.log('Inside the function')} считается выражением, потому что оно на RightHandSide. Таким образом, он выполняется без ошибок.

Есть ли способ, которым мы можем немедленно вызвать объявление функции без использования шаблона IIFE

Вы можете использовать +, что сделает объявление функции выражением.

+function(){
  console.log('done')
}()

Если вы не хотите использовать + и (), вы можете использовать new ключевое слово

new function(){
  console.log('done')
}

Extra

Очень интересный вопрос задает @ cat в комментариях. Я пытаюсь ответить на него. Есть три случая

+function(){} //returns NaN
(+function(){return 5})() //VM140:1 Uncaught TypeError: (+(intermediate value)) is not a function
+function(){return 5}() //5

+function(){} возврат NaN

+ действует здесь как Unary Plus, который разбирает значение рядом с ним на число. Как Number(function(){}) возвращает NaN, так и возвращается NaN

(+function(){return 5;})() возвращает ошибку

Обычно IIFE создаются с использованием (). () используются для объявления функции, а выражение + - короткий путь для этого. Теперь +function(){} уже является выражением, которое возвращает NaN. Поэтому вызов NaN вернет ошибку. Код такой же как

Number(function(){})()

+function(){return 5;}() возврат 5

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

Number(function(){return 5}())

В доказательстве утверждения "+ запускается после вызова функции" Рассмотрим приведенный ниже фрагмент

console.log(typeof +function(){return '5'}());

Таким образом, в приведенном выше фрагменте вы можете увидеть возвращаемое значение строки '5', но оно конвертируется в число из-за +

14 голосов
/ 13 мая 2019

Объявление функции, например

function foo() {
}

определяет (и поднимает) имя переменной foo как функцию в текущей области видимости. Объявление функции не оценивается как значение; он просто делает что-то, немного похоже на if, что-то делает (а не оценивает значение).

Вы можете вызывать только те значения, которые являются функциями, например,

<somevalue>()

где somevalue - имя переменной, которая относится к функции.

Обратите внимание, что для объявления функций требуются имена функций, потому что в противном случае нет имени переменной для назначения функции - ваш исходный

//gives `SyntaxError`
function() {
    console.log('Inside the function');
}();

бросает не из-за () в конце, а из-за отсутствия имени.

Вы можете ставить круглые скобки в конце объявления функции, если в скобках есть что-то - но эти скобки не вызывают функцию, они оцениваются как значение:

function x() {
    console.log('Inside the function');
}(console.log('some expression inside parentheses'));

Переводчик рассматривает их как два отдельных утверждения, например

function x() {
    console.log('Inside the function');
}
// completely separate:
(console.log('some expression inside parentheses'));

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

(Пустые скобки запрещены, потому что они не могут быть оценены до значения, аналогично тому, как const foo = () запрещено)

2 голосов
/ 13 мая 2019

E в IIFE обозначает выражение, и без круглых скобок ваша функция не оценивается как выражение, таким образом, синтаксическая ошибка.

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

(function() {
    console.log('Inside the function');
})();

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

function foo() {
    console.log('Inside the function');
}();

function foo() {
    console.log('Inside the function');
}(1+2);
1 голос
/ 23 мая 2019

Вы можете позвонить любым из нижеуказанных способов -

~function(){console.log("hi")}()
!function(){console.log("hi")}()
+function(){console.log("hi")}()
-function(){console.log("hi")}()
(function(){console.log("hi")}());
var i = function(){console.log("hi")}();
true && function(){ console.log("hi") }();
0, function(){ console.log("hi") }();
new function(){ console.log("hi") }
new function(){ console.log("hi") }()
1 голос
/ 13 мая 2019

Не знаю, почему вы хотите это сделать, но:

Есть ли способ, которым мы можем немедленно вызвать объявление функции без использования шаблона IIFE?

Хорошо, если для объявления функции вы имеете в виду использование ключевого слова function как в:

function name() { return this.name; }

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

Теперь, что вы на самом деле можете сделать, это использовать Function как в:

new Function('console.log("ey there")')();

Который выполнит код console.log. Нет необходимости в IIFE здесь. Но я не понимаю, как это может быть лучше, чем IIFE.

1 голос
/ 13 мая 2019

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

Объявление не может быть вызвано по вышеуказанной причине. Вы должны каким-то образом получить выражение, либо с помощью присваивания, либо с помощью группировки (IIFE). Так что это нет.

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

...