我遇到了以下代码 here :
window.requestAnimFrame = (function(callback) {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
现在我对javascript很新,我对语法有一些疑问。首先,MDN定义了requestAnimationFrame方法here,但在这个例子中,他们在最后没有()的情况下调用它,其次在最后一个分号之前似乎有一个额外的()。我不太理解两种情况下的推理,所以一些启示会非常有用!
提前感谢。
答案 0 :(得分:2)
return
对它找到的第一个函数的引用。通过这种方式,您最终会在所有浏览器上引用该函数的可用版本。(function(callback) {
并结束})
。这被称为"IIFE",是一种在JS中将代码分组在一起的方式,具有自己的变量范围,但是立即计算答案。最终结果是window.requestAnimFrame
最终指向存在的任何函数或虚拟实现window.setTimeout(callback, 1000 / 60)
。
该函数实际上并未被调用,但代码现在可以调用window.requestAnimFrame(something)
而不用担心它不存在。
答案 1 :(得分:1)
这就是所谓的立即调用函数表达式(缩写为IIFE)。您可以阅读更多有关他们的信息here。
简而言之,它是一个立即执行的函数定义,并且立即执行的返回值被赋给window.requestAnimFrame
。这只是设置window.requestAnimFrame
中的函数。 window.requestAnimFrame
之后没有任何parens,因为此代码不执行该特定功能。它正在执行其他一些函数(因此为什么最后会有parens)并将该函数的结果赋给window.requestAnimFrame
,这样当将来某个时候调用它时,它将调用相应的函数。
IIFE可以解释如下......
您将此语法知道为函数定义:
function() {
}
然后将其包含在一组额外的parens中,以便JS解释器将其视为一个表达式来进行评估:
(function() {
})
然后,为了使其执行该函数表达式,最后添加()
来实现:
(function() {
})();
然后,在该函数的代码内部执行的是return
语句,该语句将返回该立即执行的函数的结果,并将该返回值分配给window.requestAnimFrame
。以简化形式,这是:
window.requestAnimFrame = (function() {
return x;
})();
其中x
原本是一个函数本身,是其他一些计算的结果。在这种情况下使用IIFE的主要优点是预先评估一些只运行一次的代码,这样window.requestAnimFrame
只要被调用就会运行得更快。
IIFE最常见的用途是创建一个函数范围,以便从父或全局范围中隔离变量,而无需创建命名函数。
答案 2 :(得分:1)
实际上,这是一个非常有趣的函数调用嵌套。让我们从“最内在”的功能开始吧。看看它在做什么:
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
这是一个函数定义,它接受另一个函数作为参数。然后它会在超时时调用该函数。理解函数本身就是JavaScript中的对象,函数的这个定义本身就是一个对象,它将我们引向了下一个层次:
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
此代码返回一个函数对象。已经在window
对象(它找到的第一个对象)上定义的那个,或者,如果没有别的话,它最后定义的那个。同样,函数是可以像变量一样传递的对象,这只是从函数返回一个值。该值本身恰好是一个函数,可以在以后执行。
整个结构都包含在自己的功能中:
function(callback) {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
}
所以这个函数返回一个函数。然后我们将整个事物包装在括号中并执行它:
(function(callback) {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
})()
所以现在返回函数的函数会在()
之后执行。所以整个事物的价值就是一个功能。具体来说,这将评估内部函数返回的函数。然后,该函数作为值分配给变量:
window.requestAnimFrame = (function(callback) {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
所以,总的来说,整个事情的作用是为window.requestAnimFrame
分配一个函数。它是通过一些有趣的函数嵌套来实现的,但最终这就是它所做的一切。