Saat Anda menjalankan sebuah metode (yaitu fungsi yang ditugaskan ke sebuah objek), di dalamnya Anda dapat menggunakan this
variabel untuk merujuk ke objek ini, misalnya:
var obj = {
someProperty: true,
someMethod: function() {
console.log(this.someProperty);
}
};
obj.someMethod();
Jika Anda menetapkan metode dari satu objek ke objek lain, this
variabelnya merujuk ke objek baru, misalnya:
var obj = {
someProperty: true,
someMethod: function() {
console.log(this.someProperty);
}
};
var anotherObj = {
someProperty: false,
someMethod: obj.someMethod
};
anotherObj.someMethod();
Hal yang sama terjadi ketika Anda menetapkan requestAnimationFrame
metode window
ke objek lain. Fungsi asli, seperti ini, memiliki perlindungan bawaan agar tidak mengeksekusinya dalam konteks lain.
Ada Function.prototype.call()
fungsi, yang memungkinkan Anda memanggil fungsi dalam konteks lain. Anda hanya perlu meneruskannya (objek yang akan digunakan sebagai konteks) sebagai parameter pertama untuk metode ini. Misalnya alert.call({})
memberi TypeError: Illegal invocation
. Namun, alert.call(window)
berfungsi dengan baik, karena sekarang alert
dijalankan dalam lingkup aslinya.
Jika Anda menggunakan .call()
dengan objek seperti itu:
support.animationFrame.call(window, function() {});
ini berfungsi dengan baik, karena requestAnimationFrame
dijalankan dalam lingkup window
alih-alih objek Anda.
Namun, menggunakan .call()
setiap kali Anda ingin memanggil metode ini, bukanlah solusi yang sangat elegan. Sebagai gantinya, Anda bisa menggunakan Function.prototype.bind()
. Ini memiliki efek yang mirip dengan .call()
, tetapi alih-alih memanggil fungsi, ini membuat fungsi baru yang akan selalu dipanggil dalam konteks yang ditentukan. Sebagai contoh:
window.someProperty = true;
var obj = {
someProperty: false,
someMethod: function() {
console.log(this.someProperty);
}
};
var someMethodInWindowContext = obj.someMethod.bind(window);
someMethodInWindowContext();
Satu-satunya downside Function.prototype.bind()
adalah bahwa ini adalah bagian dari ECMAScript 5, yang tidak didukung di IE <= 8 . Untungnya, ada polyfill di MDN .
Seperti yang mungkin sudah Anda ketahui, Anda dapat menggunakan .bind()
untuk selalu mengeksekusi requestAnimationFrame
dalam konteks window
. Kode Anda akan terlihat seperti ini:
var support = {
animationFrame: (window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame).bind(window)
};
Kemudian Anda cukup menggunakan support.animationFrame(function() {});
.