Kiedy wykonujesz metodę (tj. Funkcję przypisaną do obiektu), wewnątrz niej możesz użyć this
zmiennej, 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 this
zmienna 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 requestAnimationFrame
metodę window
do 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 alert
jest 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ż requestAnimationFrame
jest wykonywany w zakresie window
zamiast 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ć requestAnimationFrame
w 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() {});
.