当执行一个方法(即分配给对象的函数)时,可以在其中使用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
当您分配的requestAnimationFrame
方法相同时,也会发生window
给另一个对象。诸如此类的本机功能具有内置保护,无法在其他上下文中执行它。
有一个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的一部分,IE <= 8不支持它。幸运的是,MDN上有一个polyfill。
您可能已经知道,可以使用.bind()
始终requestAnimationFrame
在的上下文中执行window
。您的代码可能如下所示:
var support = {
animationFrame: (window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame).bind(window)
};
然后,您可以简单地使用support.animationFrame(function() {});
。