在JavaScript中,如果我用圆括号调用一个函数,它会有所作为吗?
当用空括号调用一个函数,或者根本没有任何括号时,我注意到了一个区别。 然而,我没有传递任何参数的function,所以我想知道,将有什么区别:
window.onload = initAll();
和
window.onload = initAll;
请解释它背后的原理。
window.onload = initAll();
这会立即执行 initAll()
,并将函数的返回值赋给window.onload
。 这通常不是你想要的。 initAll()
将不得不返回一个函数,这是有道理的。
window.onload = initAll;
这将实际的function分配给window.onload
– 这是可能的,因为在JavaScript中,正如@Felix所说的,函数是第一类对象,而不执行它。 initAll
将由加载事件执行。
Pekka说的是正确的,但是我想用一个例子来阐述一下,这个例子可以帮助那些不完全理解函数指针或者代表的人解释。
我不会使用window.onload
因为这是有点人为的演示。 我将使用一个简单的乘法函数来演示:
function Multiply(operator, operand) { return operator * operand; }
这同样可以写成:
Multiply = function(operator, operand) { return operator * operand; }
在第一个例子中,含义可能并不明显,第二个例子更清楚地表明我们将一个具有2个参数的函数赋值给一个名为Multiply
的variables,而这个作为赋值的函数的概念在整个JavaScript中都是通用的。 这是对职能是“一等公民”这一事实的一个小例证,就是说,他们可以像传递价值观一样被传递。
所以现在对于作业的区别:
var operator = 3; var operand = 4; var ret = Multiply(operator, operand);
在定义retvariables的时候, Multiply
被执行,返回值被赋值 – ret
等于12。
让我们再以不同的方式尝试:
var operator = 3; var operand = 4; var ret = Multiply;
现在,在定义ret
, ret
成为你的Multiply
函数,而不是从你的Multiply
函数中得到的结果。 调用ret()
会导致你的Multiply
函数被执行,你可以像调用Multiply(operator, operand)
一样调用它:
var out = ret(3, 4);
是相同的
var out = Multiply(3, 4);
您已经有效地表示您将使用ret
作为Multiply()
的委托。 当调用ret
,我们确实指的是Multiply
函数。
回到你的window.onload
。 可以这样想:
window.onload = function() { //Doing what all good window.onload functions should do... } initAll = function() { return 12; }
正如你所看到的, window.onload
就像其他函数一样是一个函数,没有什么特别的。 你可以给它赋一个值,给它赋一个函数,如果你愿意,可以把它清空 – 重点是关于window.onload
没有什么特别的东西比关于你自己的函数。 唯一稍微不同的是它被加载时被窗口调用。 [免责声明:我从来没有真正清除窗口函数,所以我不知道这是否会造成负面影响。 我们希望在调用它之前检查函数是否被赋值, if (window.onload) window.onload();
]。
现在调用initAll()
我们所说的是:
window.onload = initAll();
这还不如说:
window.onload = 12;
但是当我们说没有括号的initAll
时,我们真正说的是:我想用一个新的函数replace我的window.onload函数,即我想用我的initAll
函数replace它,这样任何调用window.onload
运行我的initAll
代码。
所以:
window.onload = function() { //Doing what all good window.onload functions should do... }
被replace为:
window.onload = function() { return 12; }
所以对window.onload
任何调用都会执行你的initAll
函数,而不是最初的任何window.onload
。 你已经用你的新function取代了原来的function。
事实上,你可以平等地写:
window.onload = function() { //Write all your init code right in here instead of having a separate //initAll function. }
另一个可能更好的例子是:
var d = new Date(); var currentTime = d.getTime();
无论什么时候在d
被定义的时候结束分配给currentTime
。 好极了,但是这只有在我们想知道什么时候包含这个代码的函数被调用的时候才有用 – 也就是在页面加载的时候。 如果我们想在任何时候调用currentTime
来调用当前时间呢?
var currentTime = function() { var d = new Date(); return d.getTime(); } var a = currentTime(); //The current time at the point a is defined... var b = currentTime; //b is a functional reference to currentTime... var c = b(); //The current time when variable c is defined var d = c; //The current time when variable c was defined
请注意,我们如何在我们的c
和d
赋值中完全按照我们可以调用currentTime()
调用b()
currentTime()
?
javascript中的函数是一等公民,因此可以分配给其他variables或作为parameter passing。
所以,当你这样做
window.onload = initAll;
您正在设置window
对象的onload
属性来引用initAll
函数本身。
当你这样做
window.onload = initAll();
您正在设置onload
属性来保存initAll的返回值 ,因为它将在该行上执行。
initAll
是对函数值的引用,括号运算符附加到函数名称RUNS这个函数对象。
所以如果你做类似的事情
a = initAll
那么a
将会变得像initAll
– 例如你可以做a()
– 但是
a = initAll()
variablesa
将得到执行的initAll
函数的返回值
我迟了6年,但我觉得这可能比上面的答案简单得多。
所以这里是TLDR ; 或者在使用和不使用()
时调用函数时的鸟瞰图
让我们以这个function为例:
function foo(){ return 123; }
如果你login“foo” – 没有 ()
console.log(foo); ---outout------ function foo(){ return 123; }
使用no ()
意味着获取函数本身 。 如果你想把它作为callback传递,你会这样做。
如果你logging“foo()” – with ()
console.log(foo()); -----output----- 123
在函数之后使用()
意味着执行函数并返回它的值 。