Kiedy wykonujesz metodę (tj. Funkcję przypisaną do obiektu), wewnątrz niej możesz użyć thiszmiennej, aby odwołać się do tego obiektu, na przykład:
var obj = {
someProperty: true,
someMethod: function() {
console.log(this.someProperty);
}
};
obj.someMethod(); // logs true
Jeśli przypiszesz metodę z jednego obiektu do innego, jej thiszmienna odwołuje się do nowego obiektu, na przykład:
var obj = {
someProperty: true,
someMethod: function() {
console.log(this.someProperty);
}
};
var anotherObj = {
someProperty: false,
someMethod: obj.someMethod
};
anotherObj.someMethod(); // logs false
To samo dzieje się, gdy przypiszesz requestAnimationFramemetodę windowdo innego obiektu. Funkcje natywne, takie jak ta, mają wbudowaną ochronę przed wykonywaniem ich w innym kontekście.
Istnieje Function.prototype.call()funkcja, która umożliwia wywołanie funkcji w innym kontekście. Musisz tylko przekazać go (obiekt, który będzie używany jako kontekst) jako pierwszy parametr tej metody. Na przykład alert.call({})daje TypeError: Illegal invocation. Jednak alert.call(window)działa dobrze, ponieważ teraz alertjest wykonywany w swoim oryginalnym zakresie.
Jeśli używasz .call()ze swoim obiektem w ten sposób:
support.animationFrame.call(window, function() {});
działa dobrze, ponieważ requestAnimationFramejest wykonywany w zakresie windowzamiast obiektu.
Jednak używanie za .call()każdym razem, gdy chcesz wywołać tę metodę, nie jest zbyt eleganckim rozwiązaniem. Zamiast tego możesz użyć Function.prototype.bind(). Ma podobny efekt .call(), ale zamiast wywoływać funkcję, tworzy nową funkcję, która zawsze będzie wywoływana w określonym kontekście. Na przykład:
window.someProperty = true;
var obj = {
someProperty: false,
someMethod: function() {
console.log(this.someProperty);
}
};
var someMethodInWindowContext = obj.someMethod.bind(window);
someMethodInWindowContext(); // logs true
Jedynym minusem Function.prototype.bind()jest to, że jest częścią ECMAScript 5, który nie jest obsługiwany w IE <= 8 . Na szczęście na MDN jest polyfill .
Jak prawdopodobnie już się zorientowałeś, możesz użyć, .bind()aby zawsze wykonywać requestAnimationFramew kontekście window. Twój kod może wyglądać następująco:
var support = {
animationFrame: (window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame).bind(window)
};
Następnie możesz po prostu użyć support.animationFrame(function() {});.