首页 > 为什么function a(b){alert(b)}(1) 不会报错

为什么function a(b){alert(b)}(1) 不会报错

当在函数声明之后直接加括号,如下

function a(){
    alert(1)
}()

会报 Unexpected token 错误,查阅了资料后知道函数声明之后是不能直接加括号执行的,需要将函数声明转化为函数表达式。如下:

!function a(){alert(1)}()  // true  ,(也可以将!换成 +、-、~ 中的任一个)。
(function a(){alert(1)})() // undefined
(function a(){alert(1)}()) // undefined

当我试着写了如下代码时:

function a(b){alert(b)}(1)  // 1
alert(a)   // function a(b){alert(b)}

为什么第一行代码会在控制台输出 1? 第二行代码会弹出 function a(b){alert(b)}?


这是一个函数定义,但是不符合函数定义规范,所以保错

function a(){
    console.log(1);
}();

也是一个函数定义,此时(2)是一个分组运算,@rambo_panda 提到的,计算优先级提升,计算完毕后不影响原来函数的定义

function a(){
    console.log(1);
}(2);

其和一下等价

function a(){
    console.log(1);
}
(2);

//也和这个等价

function a(){console.log(1);}(2);

!function a(){console.log(1);}()  // 函数被执行,返回结果true 
(function a(){console.log(1);})() // 函数被执行,返回结果undefined
(function a(){console.log(1);}()) // 函数被执行,返回结果undefined

为什么大神们都要从函数的角度去分析呢?

运算符 运算符 他是用来计算 、 赋值、 等操作。
只不过 分组运算符 () 特殊。 他可以 提升变量优先级

任何一个运算符,单独使用都会报错

+;  //  Uncaught SyntaxError: Unexpected token }(…)   你让我加谁啊?
*;  //  你他妈让我 谁乘谁 啊?

// 同理
();  // 同理 你让我做什么??  我 

var a = (1);
var b = (undefined);
var a1 = +1;
var a2 = *1; // TODO 骚年 失望了吧?  * / 这些有一个专用名词我压根没记住(最他妈讨厌记这些概念) 意思就是 有些 运算符 是必须 >1个参数 你才能使用。 - +  单参运算符  * / 多参运算符  (请允许我私自这么叫吧)  


这是个有意思的问题,尝试分析下。

在 ECMAScript 中,函数声明 (Function declaration, FD)与 具名函数表达式(Named function expresson, NFE)具有相同的语法:

FunctionDeclaration :
function Identifier ( FormalParameterListopt ) { FunctionBody }
FunctionExpression :
function Identifieropt ( FormalParameterListopt ) { FunctionBody }

function a(b) {alert(b)} 到底是一个 FD 还是一个 NFE 取决于它所处的位置,例如在 IIFE 结构(function a(b) {alert(b)})() 中,函数被包裹在分组运算符 ()中,此时该函数就是一个 NFE,因为分组运算符只接受表达式。把函数放在 !, +, !, void 等运算符后面也是同理,明确地表示该函数是一个 NFE。

相反,当 function a(b) {alert(b)} 出现在语句开头的时候,它就被解析为一个 FD,而不是 NFE。因此,function a(b){alert(b)}(1) 被解析为两条语句:

function a(b) {alert(b)}  // FD
(1)      // 表达式语句

console 显示的 1(1) 求值的结果。(你可以把 function a(b){alert(b)}(1) 复制到JavaScript AST visualizer 查看生成的抽象语法树)

alert(a)会对 a 进行隐式的类型转换,以 String 为 hint 调用 a[[toPrimitive]] 内部方法,实际就是调用 a.toString,然后再 alert,所以在模态对话框中显示 a 函数的字符串表示。


因为a被toString了

【热门文章】
【热门文章】