When you execute a method (i.e. function assigned to an object), inside it you can use this variable to refer to this object, for example:
var obj = { someProperty: true, someMethod: function() { console.log(this.someProperty); } }; obj.someMethod(); // logs true
If you assign a method from one object to another, its this variable refers to the new object, for example:
var obj = { someProperty: true, someMethod: function() { console.log(this.someProperty); } }; var anotherObj = { someProperty: false, someMethod: obj.someMethod }; anotherObj.someMethod(); // logs false
The same thing happens when you assign requestAnimationFrame method of window to another object. Native functions, such as this, has build-in protection from executing it in other context.
There is a Function.prototype.call() function, which allows you to call a function in another context. You just have to pass it (the object which will be used as context) as a first parameter to this method. For example alert.call({}) gives TypeError: Illegal invocation. However, alert.call(window) works fine, because now alert is executed in its original scope.
If you use .call() with your object like that:
support.animationFrame.call(window, function() {});
it works fine, because requestAnimationFrame is executed in scope of window instead of your object.
However, using .call() every time you want to call this method, isn't very elegant solution. Instead, you can use Function.prototype.bind(). It has similar effect to .call(), but instead of calling the function, it creates a new function which will always be called in specified context. For example:
window.someProperty = true; var obj = { someProperty: false, someMethod: function() { console.log(this.someProperty); } }; var someMethodInWindowContext = obj.someMethod.bind(window); someMethodInWindowContext(); // logs true
The only downside of Function.prototype.bind() is that it's a part of ECMAScript 5, which is not supported in IE <= 8. Fortunately, there is a polyfill on MDN.
As you probably already figured out, you can use .bind() to always execute requestAnimationFrame in context of window. Your code could look like this:
var support = { animationFrame: (window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || window.oRequestAnimationFrame).bind(window) };
Then you can simply use support.animationFrame(function() {});.