当你执行一个方法(即分配给一个对象的函数)时,你可以在其中使用this变量来引用这个对象,例如:
var obj = {
someProperty: true,
someMethod: function() {
console.log(this.someProperty);
}
};
obj.someMethod(); // logs true
如果将一个对象的方法分配给另一个对象,则其this 变量指的是新对象,例如:
var obj = {
someProperty: true,
someMethod: function() {
console.log(this.someProperty);
}
};
var anotherObj = {
someProperty: false,
someMethod: obj.someMethod
};
anotherObj.someMethod(); // logs false
当您将window 的requestAnimationFrame 方法分配给另一个对象时,也会发生同样的事情。诸如 this 的原生函数具有内置保护,可防止在其他上下文中执行它。
有一个Function.prototype.call() 函数,它允许您在另一个上下文中调用一个函数。您只需将它(将用作上下文的对象)作为第一个参数传递给此方法。例如alert.call({}) 给出TypeError: Illegal invocation。但是,alert.call(window) 工作正常,因为现在 alert 在其原始范围内执行。
如果您将.call() 与您的对象一起使用:
support.animationFrame.call(window, function() {});
它工作正常,因为requestAnimationFrame 是在window 范围内执行的,而不是你的对象。
但是,每次您想调用此方法时都使用.call(),这不是很优雅的解决方案。相反,您可以使用Function.prototype.bind()。它与.call() 具有类似的效果,但它不是调用函数,而是创建一个始终在指定上下文中调用的新函数。例如:
window.someProperty = true;
var obj = {
someProperty: false,
someMethod: function() {
console.log(this.someProperty);
}
};
var someMethodInWindowContext = obj.someMethod.bind(window);
someMethodInWindowContext(); // logs true
Function.prototype.bind() 的唯一缺点是它是 ECMAScript 5 的一部分,is not supported in IE <= 8。还好有a polyfill on MDN。
您可能已经知道,您可以使用.bind() 在window 的上下文中始终执行requestAnimationFrame。您的代码可能如下所示:
var support = {
animationFrame: (window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame).bind(window)
};
那么你可以简单地使用support.animationFrame(function() {});。