Khi bạn thực thi một phương thức (tức là hàm được gán cho một đối tượng), bên trong nó, bạn có thể sử dụng this
biến để tham chiếu đến đối tượng này, ví dụ:
var obj = {
someProperty: true,
someMethod: function() {
console.log(this.someProperty);
}
};
obj.someMethod(); // logs true
Nếu bạn gán một phương thức từ đối tượng này sang đối tượng khác, this
ví dụ , biến của nó đề cập đến đối tượng mới:
var obj = {
someProperty: true,
someMethod: function() {
console.log(this.someProperty);
}
};
var anotherObj = {
someProperty: false,
someMethod: obj.someMethod
};
anotherObj.someMethod(); // logs false
Điều tương tự xảy ra khi bạn gán requestAnimationFrame
phương thức window
cho đối tượng khác. Các hàm riêng, chẳng hạn như hàm này, có bảo vệ tích hợp để thực thi nó trong ngữ cảnh khác.
Có một Function.prototype.call()
chức năng, cho phép bạn gọi một chức năng trong ngữ cảnh khác. Bạn chỉ cần truyền nó (đối tượng sẽ được sử dụng làm bối cảnh) làm tham số đầu tiên cho phương thức này. Ví dụ alert.call({})
cho TypeError: Illegal invocation
. Tuy nhiên, alert.call(window)
hoạt động tốt, bởi vì bây giờ alert
được thực hiện trong phạm vi ban đầu của nó.
Nếu bạn sử dụng .call()
với đối tượng của mình như thế:
support.animationFrame.call(window, function() {});
nó hoạt động tốt, bởi vì requestAnimationFrame
được thực thi trong phạm vi window
thay vì đối tượng của bạn.
Tuy nhiên, sử dụng .call()
mỗi khi bạn muốn gọi phương thức này, không phải là giải pháp rất thanh lịch. Thay vào đó, bạn có thể sử dụng Function.prototype.bind()
. Nó có tác dụng tương tự .call()
, nhưng thay vì gọi hàm, nó tạo ra một hàm mới sẽ luôn được gọi trong ngữ cảnh được chỉ định. Ví dụ:
window.someProperty = true;
var obj = {
someProperty: false,
someMethod: function() {
console.log(this.someProperty);
}
};
var someMethodInWindowContext = obj.someMethod.bind(window);
someMethodInWindowContext(); // logs true
Nhược điểm duy nhất của Function.prototype.bind()
nó là một phần của ECMAScript 5, không được hỗ trợ trong IE <= 8 . May mắn thay, có một polyfill trên MDN .
Như bạn có thể đã tìm ra, bạn có thể sử dụng .bind()
để luôn luôn thực thi requestAnimationFrame
trong bối cảnh window
. Mã của bạn có thể trông như thế này:
var support = {
animationFrame: (window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame).bind(window)
};
Sau đó, bạn có thể chỉ cần sử dụng support.animationFrame(function() {});
.