先说结果
1、加了括号的代表执行完毕得到函数的结果(括号的二义性,是“函数的调用运算符”)
2、没加括号的,查看该函数的完整信息。指向函数的指针,只是传递了函数题所在的地址位置。
举例:
//demo1
function demo1() {
var m = 3;
alert(m);
}
function demo2() {
var m = 55;
alert(m);
}
var e = document.getElementById('btn');
// 点击的时候才进行执行 点击按钮“btn”后弹出3
e.addEventListener('click', demo1);
// 直接就已经弹出进行了执行 弹出55
e.addEventListener('click', demo2());
//demo2
function foo(){
var m = 3;
return m;
}
var a = foo;
var b = foo();
console.log(a); //函数体
console.log(b);//3
其中括号的二义性。感觉像通假字,可以有俩意思。比如一个用红色墨水写的“蓝”字。这个字是什么颜色?蓝?红?
2.7.2 括号"( )"的二义性
我们来看下面语句中的括号"( )"应该是什么含义呢?
var str = typeof(123);
var str = ('please input a string', 1000);
第一个 typeof 看起来好像被当成了函数使用--这是否说明 typeof 为一个"内部函数"呢?而第二行代码,你相信它会成功执行并使 str"意外地"赋值为 1000 吗?括号首先可以作为语句中的词法元素。例如函数声明中的"虚拟参数表":
//声明函数时,括号用做参数表
function foo(v1, v2) {
//…
}
第二种情况,就是括号只作为"传值参数表(这有别于函数声明中的'虚拟参数表')",注意这里它并不表达函数调用的含义。目前为止,它只出现在 new 关键字的使用中:new关键字用于创建一个对象实例并负责调用该构造器函数,如果存在一对括号"( )"指示的参数表,则在调用构造器函数时传入该参数表,对此的具体分析,我们已经在"2.5.1.1使用构造器创建对象实例"中讲述过了。例如:
//构造对象时,用于传入初始化参数
var myArray = new Array('abc', 1, true);
接下来,它也可以在 with、for、if、while 和 do...while 等语句,以及 catch()等子句中用来作为限定表达式的词法元素:
// for语句(for…in语句类同)
for ( initialize; test; increment )
statement
// if语句
if ( expression )
statement
// while语句
while ( expression )
statement
// do…while语句
do
statement
while ( expression )
在充当 if、while 和 do...while 语句中的词法元素时,括号会有"将表达式结果转换为布尔值"的副作用(参见"5.7.3.2语句(语义)导致的类型转换")。在很多时候,语句中的括号会产生类似于"运算"这样的附加效果。
第四种情况,是括号"( )"用于强制表达式运算。这种情况下,基本含义是我们通常说的强制运算优先级。但事实上,不管有没有优先级的问题,括号总是会强制其内部的代码作为表达式运算。例如我们在这一小节开始列举的例子:
var str1 = typeof(123);
var str2 = ('please input a string', 1000);
在第 1 行代码中,"( )"强制 123 作为单值表达式运算,当然运算结果还是 123,于是再进行 typeof 运算。所以这里的一对括号起到了强制运算的作用。同样的道理,第 2 行代码里的一对括号也起到相同的作用,它强制两个单值表达式做连续运算,由于连续运算符","的返回值是最后一个表达式的值,因此这个结果返回了 1000。所以我们要意识到,上面的第 1 行代码并没有调用函数的意思,而第 2 行代码将使 str2 被赋值为 1000。
最后一种情况最为常见:作为函数/方法调用运算符。例如:
//有(),表明函数调用
foo();
//没有(),则该语句只是一个变量的返回。
foo;
我们一再强调:函数调用过程中的括号"( )"是运算符。也因此得出推论,当"( )"作为运算符时,它只作用于表达式运算,而不可能作用于语句。所以你只能将位于:
function foo() {
return( 1 + 2);
}
这个函数内的、return 之后的括号理解成"强制表达式优先级",而不是理解成"把 return当成函数或运算符使用"。所以从代码格式化的角度上来说,在下面两种书写方法中,第二种才是正确的:
//第一种,像函数调用一样,return后无空格
return(1 + 2);
//第二种,return后置一空格
return (1 + 2);
基于同样的理由,无论"break (my_label)"看起来如何合理,也会被引擎识别为语法错误。因为 my_label 只是一个标签,而不是可以交给"( )"运算符处理的运算元,标签与运算元属于两个各自独立的、可重复(而不发生覆盖)的标识符系统。