Khi bạn thực hiện một phương pháp (tức là chức năng được gán cho một đối tượng), bên trong nó, bạn có thể sử dụng this
biến để đề cập đế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 pháp từ một đối tượng khác, biến this
của nó đề cập đến đối tượng mới, ví dụ:
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ự cũng xảy ra khi bạn gán requestAnimationFrame
phương pháp window
đối tượng khác . Các hàm nguyên gốc, chẳng hạn như này, có tính năng bảo vệ tích hợp để thực hiện nó trong ngữ cảnh khác.
Có chức năng Function.prototype.call()
, cho phép bạn gọi hàm trong ngữ cảnh khác. Bạn chỉ cần truyền nó (đối tượng sẽ được sử dụng làm ngữ 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 bạn như thế:
support.animationFrame.call(window, function() {});
nó hoạt động tốt, vì requestAnimationFrame
được thực hiện 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 pháp 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ó hiệu ứng tương tự như .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()
là nó là một phần của ECMAScript 5, is not supported in IE <= 8. May mắn thay, có a polyfill on MDN.
Như bạn có thể đã tìm ra, bạn có thể sử dụng .bind()
để luôn thực hiện requestAnimationFrame
trong ngữ cảnh window
. Mã của bạn có thể trông giống như sau:
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() {});
.
Kể từ Chrome 33, cuộc gọi thứ hai cũng không thành công với "Yêu cầu bất hợp pháp". Hạnh phúc để loại bỏ các downvote khi câu trả lời là [cập nhật] (http://stackoverflow.com/a/13278323/1269037)! –
@DanDascalescu: Tôi đang sử dụng chrome 33 và nó đang hoạt động cho tôi. – Nemoy
Tôi vừa sao chép mã của bạn và nhận được lỗi yêu cầu bất hợp pháp. [Đây là screencast.] (Http://imgur.com/oTDsazG) –