Ketika saya menggunakan requestAnimationFrame
untuk melakukan beberapa animasi yang didukung asli dengan kode di bawah ini:
var support = {
animationFrame: window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame
};
support.animationFrame(function() {}); //error
support.animationFrame.call(window, function() {}); //right
Panggilan langsung support.animationFrame
akan memberi ...
TypeError Tidak Tertangkap: Permintaan ilegal
di Chrome. Mengapa?
sumber
myObj.myAlert('this is an alert');
ilegal. Penggunaan yang benar adalahmyObj.myAlert.call(window, 'this is an alert')
. Silakan baca jawaban dengan benar dan cobalah untuk memahaminya.Anda juga bisa menggunakan:
var obj = { alert: alert.bind(window) }; obj.alert('I´m an alert!!');
sumber
var realReplaceState = history.replaceState.bind(history);
.bind(localStorage)
, bukan.bind(window)
.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(); // logs true
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(); // logs false
Hal yang sama terjadi ketika Anda menetapkan
requestAnimationFrame
metodewindow
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. Misalnyaalert.call({})
memberiTypeError: Illegal invocation
. Namun,alert.call(window)
berfungsi dengan baik, karena sekarangalert
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 lingkupwindow
alih-alih objek Anda.Namun, menggunakan
.call()
setiap kali Anda ingin memanggil metode ini, bukanlah solusi yang sangat elegan. Sebagai gantinya, Anda bisa menggunakanFunction.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(); // logs true
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 mengeksekusirequestAnimationFrame
dalam kontekswindow
. 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() {});
.sumber