javascript,将 requestAnimationFrame 和 cancelAnimationFrame 分配给对象的属性
javascript, assigning requestAnimationFrame & cancelAnimationFrame to properties of an object
//
// version 1
//
var requestAnimFram = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequsetAnimationFrame ||
function(callback){
window.setTimeout(callback, 1000 / 60);
}
})();
//version 1 usage
function main(){
//main loop
...
requestAnimFram(main);
}
main();
//
// version 2
//
var animFram = {
req: window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback){
window.setTimeout(callback, 1000 / 60);
},
ccl: window.cancelAnimationFrame ||
window.mozCancelAnimationFrame,
myReq: 0
};
//version 2 usage
function main(){
...
aniFram.myReq = aniFram.req(main);
}
main();
function stop(){
aniFram.ccl(myReq);
}
在探索一些示例代码时,我发现了 requestAnimationFrame
。版本 1 是从中雕刻出来的,它工作正常。找了一会儿,我也找到了cancelAnimationFrame
,想两个都用。所以我制作了一个虚拟页面进行测试。版本2是从它雕刻出来的。
问题是,它没有循环。所以,我有两个问题。
这样用requestAnimationFrame
不就不行了吗?如果是,为什么会这样?
如果可能的话-但我做错了,我该如何实现?
这是一个副本("Uncaught TypeError: Illegal invocation" in Chrome)。但我还是会更详细地回答我自己的问题,这样可以帮助其他人以不同的方式理解这件事。
- Is it impossible to use requestAnimationFrame in this way? If so, why exactly so?
不可能。
- If it's possible-but I'm doing it in wrong way, how can I acheive this?
这个问题本身可以通过使用 call()
和 bind()
以及 apply()
方法轻松解决。
//Using call()
//Attach call method during invocation
aniFram.req.call(window, main);
//Using bind()
//Attach bind method during the object initialization
aniFram = {
req: requestAnimationFrame.bind(window)
...
}
aniFram.req(main);
//Using apply()
//Attach apply method during invocation
aniFram.req.apply(window, [main]);
请注意这里的相似之处,即所有 3 种方法都有一个额外的参数 'window'。它们都有相同的原因:requestAnimationFrame
是 window
对象的方法,需要 window
.
的上下文
aniFram
是一个对象。它有一个引用 window.requestAnimationFrame
的方法 req
。 aniFram.req(main)
在 aniFram
的上下文中调用 window.requestAnimationFrame
,而不是 window
。这就是为什么它不起作用。让我们考虑另一个示例代码:
示例代码
var obj1 = {
target: 'Jake',
hitman: function(){
this.target = 'RIP';
}
};
var obj2 = {
//assigns obj1.hitman to obj2.hitman
hitman: obj1.hitman
};
obj2.hitman();
console.log(obj1.target); //outputs 'Jake'
/////////////////////////////////////////
//call() method
obj2.hitman.call(obj1);
console.log(obj1.target); //outputs 'RIP'
//apply() method
obj2.hitman.apply(obj1);
console.log(obj1.target); //outputs 'RIP'
//bind() method
var obj2 = {
hitman: obj1.hitman.bind(obj1)
};
obj2.hitman();
console.log(obj1.target); //outputs 'RIP'
这与您的代码版本 2 的情况完全相同。您调用引用 obj1.hitman
的 obj2.hitman()
希望更改 obj1.target
的值,但它什么也没做。因为 obj1.hitman
所做的是执行一条语句 this.target = 'RIP'
。由于是在obj2
的上下文中执行的,所以这条语句就变成了obj2.target = 'RIP'
。 obj2.
中没有target
属性
调用、申请、绑定
这就是这些方法发挥作用的地方。如果没有它们,Javascript 引擎会自动确定上下文(当前对象。即 aniFram、obj2)。通过将这些方法附加到您的代码,现在您可以决定在哪个上下文中执行它(即 window, obj1)。
这也称为别名函数。 (If Javascript has first-class functions, why doesn't this work?)
//
// version 1
//
var requestAnimFram = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequsetAnimationFrame ||
function(callback){
window.setTimeout(callback, 1000 / 60);
}
})();
//version 1 usage
function main(){
//main loop
...
requestAnimFram(main);
}
main();
//
// version 2
//
var animFram = {
req: window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback){
window.setTimeout(callback, 1000 / 60);
},
ccl: window.cancelAnimationFrame ||
window.mozCancelAnimationFrame,
myReq: 0
};
//version 2 usage
function main(){
...
aniFram.myReq = aniFram.req(main);
}
main();
function stop(){
aniFram.ccl(myReq);
}
在探索一些示例代码时,我发现了 requestAnimationFrame
。版本 1 是从中雕刻出来的,它工作正常。找了一会儿,我也找到了cancelAnimationFrame
,想两个都用。所以我制作了一个虚拟页面进行测试。版本2是从它雕刻出来的。
问题是,它没有循环。所以,我有两个问题。
这样用
requestAnimationFrame
不就不行了吗?如果是,为什么会这样?如果可能的话-但我做错了,我该如何实现?
这是一个副本("Uncaught TypeError: Illegal invocation" in Chrome)。但我还是会更详细地回答我自己的问题,这样可以帮助其他人以不同的方式理解这件事。
- Is it impossible to use requestAnimationFrame in this way? If so, why exactly so?
不可能。
- If it's possible-but I'm doing it in wrong way, how can I acheive this?
这个问题本身可以通过使用 call()
和 bind()
以及 apply()
方法轻松解决。
//Using call()
//Attach call method during invocation
aniFram.req.call(window, main);
//Using bind()
//Attach bind method during the object initialization
aniFram = {
req: requestAnimationFrame.bind(window)
...
}
aniFram.req(main);
//Using apply()
//Attach apply method during invocation
aniFram.req.apply(window, [main]);
请注意这里的相似之处,即所有 3 种方法都有一个额外的参数 'window'。它们都有相同的原因:requestAnimationFrame
是 window
对象的方法,需要 window
.
aniFram
是一个对象。它有一个引用 window.requestAnimationFrame
的方法 req
。 aniFram.req(main)
在 aniFram
的上下文中调用 window.requestAnimationFrame
,而不是 window
。这就是为什么它不起作用。让我们考虑另一个示例代码:
示例代码
var obj1 = {
target: 'Jake',
hitman: function(){
this.target = 'RIP';
}
};
var obj2 = {
//assigns obj1.hitman to obj2.hitman
hitman: obj1.hitman
};
obj2.hitman();
console.log(obj1.target); //outputs 'Jake'
/////////////////////////////////////////
//call() method
obj2.hitman.call(obj1);
console.log(obj1.target); //outputs 'RIP'
//apply() method
obj2.hitman.apply(obj1);
console.log(obj1.target); //outputs 'RIP'
//bind() method
var obj2 = {
hitman: obj1.hitman.bind(obj1)
};
obj2.hitman();
console.log(obj1.target); //outputs 'RIP'
这与您的代码版本 2 的情况完全相同。您调用引用 obj1.hitman
的 obj2.hitman()
希望更改 obj1.target
的值,但它什么也没做。因为 obj1.hitman
所做的是执行一条语句 this.target = 'RIP'
。由于是在obj2
的上下文中执行的,所以这条语句就变成了obj2.target = 'RIP'
。 obj2.
target
属性
调用、申请、绑定
这就是这些方法发挥作用的地方。如果没有它们,Javascript 引擎会自动确定上下文(当前对象。即 aniFram、obj2)。通过将这些方法附加到您的代码,现在您可以决定在哪个上下文中执行它(即 window, obj1)。
这也称为别名函数。 (If Javascript has first-class functions, why doesn't this work?)