立即调用函数表达式,无需使用分组运算符

时间:2019-05-13 08:28:10

标签: javascript function iife

我正在尝试不使用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 个答案:

答案 0 :(得分:14)

函数声明,例如

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 = ()的方式)

答案 1 :(得分:14)

在您的代码中,您没有该函数的名称,这是语法错误的原因。即使您有名字,也会抛出错误。

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

原因是函数声明没有返回函数的值,但是当您将函数声明包装在()中时,它将强制它成为返回值的函数表达式。

在第二个示例中,function() {console.log('Inside the function')}被视为表达式,因为它位于RightHandSide上。因此它执行时没有错误。

  

有没有一种方法可以立即调用函数声明而无需使用IIFE模式

您可以使用+来使函数声明成为表达式。

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

如果您不想使用+(),则可以使用new关键字

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

额外

@cat 在评论中提出了一个非常有趣的问题。我尝试回答。有三种情况

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

+function(){}返回NaN

+在这里用作一元加号,它将其旁边的值解析为数字。由于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',但是由于+而被转换为数字

答案 2 :(得分:2)

IIFE中的 E 代表表达式,如果没有环绕括号,则不会将您的函数作为表达式进行评估,因此语法错误。

创建表达式是一种欺骗解释器并能够立即调用该函数的方法

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

在您的示例中,您有一个后跟grouping operator的函数语句,但是由于两个原因,它在语法上是错误的,首先是它没有名称,其次是因为分组运算符必须在其中包含表达式,实际上,如果您添加一个有效的错误,错误将消失,但仍然无法获得理想的结果。

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

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

答案 3 :(得分:1)

要调用某些东西,它必须是一个函数值,声明只是声明一个名称,而不会求值到函数值本身,因此您不能调用它。

由于上述原因,不能调用声明。您必须通过分配或分组(IIFE)以某种方式结束表达式。所以这不是。

如果您为我们提供了更多有关为什么要这样做的背景信息,也许我们可以为您提供建议。

答案 4 :(得分:1)

不确定为什么要这么做,但是:

  

有没有一种方法可以立即调用函数声明而无需使用IIFE模式?

好吧,如果要进行功能声明,则表示使用关键字function,如下所示:

function name() { return this.name; }

据我所知,没有。如果我理解正确的话,您需要使用额外的括号告诉运行时不要将函数分配给name变量。

现在,您实际可以做的是使用Function,如下所示:

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

将执行console.log代码。这里不需要IIFE。但是我不认为这会比IIFE更好。

答案 5 :(得分:0)

您可以通过以下两种方式致电-

~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") }()