将 requestAnimationFrame 分配给对象变量时出现类型错误
Type Error when assigning requestAnimationFrame to object variable
我遇到了这个奇怪的 Type Error
,当我尝试创建对 window.requestAnimationFrame
的本地引用时,它一直在发生。以下按预期工作并将记录 Foo
:
var foo = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(fn){ setTimeout(fn, 1000 / 24); };
foo(function(){ console.log('Foo') });
然而,当我绑定到父对象时,它不起作用并抛出 Type Error
,我不得不说这让我感到困惑:
var bar = {};
bar.foo = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(fn){ setTimeout(fn, 1000 / 24); };
bar.foo(function(){ console.log('Bar.Foo') });
即使 window
或 window.requestAnimationFrame
永远不会 undefined
,调用它们也会在嵌套时引发类型错误。但是,当我比较两个变量时,它们被认为是相等的。是否有一个原因?有没有一种方法可以撕毁对对象内部正确实现的工作引用?
document.body.innerHTML += 'About to call Foo: <br />';
try {
var foo = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(fn){ setTimeout(fn, 1000 / 24); };
foo(function(){ document.body.innerHTML += '<i>Foo</i><br />'; });
} catch(e){
document.body.innerHTML += '<i> >>> Error thrown when calling Foo.</i><br />';
}
document.body.innerHTML += 'About to call Bar.Foo: <br />';
try {
var bar = {};
bar.foo = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(fn){ setTimeout(fn, 1000 / 24); };
bar.foo(function(){ document.body.innerHTML += '<i>Bar.Foo</i><br />'; });
} catch(e){
document.body.innerHTML += '<i> >>> Error thrown when calling Bar.Foo.</i><br />';
}
document.body.innerHTML += foo === bar.foo
? '<strong>Foo and Bar.Foo are considered the same</strong><br />'
: '<strong>Foo and Bar.Foo are NOT considered the same</strong><br />';
body {
font-family: Monaco, 'Courier MS', Coureire, mono-space;
}
嗯,requestAnimationFrame
是 DOM API 的一部分,它不是 JavaScript 对象,所以很难 确定 失败的原因。请记住:
- JavaScript 中的函数在
this
设置为调用者对象的情况下进行分派,在您的情况下,该对象是 bar
,它不具有所有属性 window
有。
- default 对象 JavaScript 函数是用
window
调度的 - 所以调用 window.alert
和 alert
是一样的事情(严格模式除外)。
所以,它完全有可能在幕后某处使用 this
。再一次,它是 "Host Object" 所以所有赌注都关闭了。
这是具有相同行为的类似 "plain" JS 代码。
window.msg = "Hello";
function foo(){
if(this !== window) throw new TypeError("Illegal Invocation");
alert(this.msg);
}
foo(); // alerts hello, `this` is window
window.foo(); // alerts hello
var bar = {};
bar.foo = foo;
bar.foo(); // typeerror
解决方法是将其包装在匿名函数中或使用 bind
.
试试这个
var bar = {};
bar.foo = (window.requestAnimationFrame && window.requestAnimationFrame.bind(window)) ||
(window.webkitRequestAnimationFrame && window.webkitRequestAnimationFrame.bind(window)) ||
(window.mozRequestAnimationFrame && window.mozRequestAnimationFrame.bind(window)) ||
(window.msRequestAnimationFrame && window.msRequestAnimationFrame.bind(window)) ||
function(fn){ setTimeout(fn, 1000 / 24); };
bar.foo(function(){ console.log('Bar.Foo') });
这会将 *requestAnimation 的 this
设置为 window 对象
根据@poke 的评论
var bar = {};
bar.foo = (window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(fn){ setTimeout(fn, 1000 / 24); }).bind(window);
bar.foo(function(){ console.log('Bar.Foo') });
我遇到了这个奇怪的 Type Error
,当我尝试创建对 window.requestAnimationFrame
的本地引用时,它一直在发生。以下按预期工作并将记录 Foo
:
var foo = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(fn){ setTimeout(fn, 1000 / 24); };
foo(function(){ console.log('Foo') });
然而,当我绑定到父对象时,它不起作用并抛出 Type Error
,我不得不说这让我感到困惑:
var bar = {};
bar.foo = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(fn){ setTimeout(fn, 1000 / 24); };
bar.foo(function(){ console.log('Bar.Foo') });
即使 window
或 window.requestAnimationFrame
永远不会 undefined
,调用它们也会在嵌套时引发类型错误。但是,当我比较两个变量时,它们被认为是相等的。是否有一个原因?有没有一种方法可以撕毁对对象内部正确实现的工作引用?
document.body.innerHTML += 'About to call Foo: <br />';
try {
var foo = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(fn){ setTimeout(fn, 1000 / 24); };
foo(function(){ document.body.innerHTML += '<i>Foo</i><br />'; });
} catch(e){
document.body.innerHTML += '<i> >>> Error thrown when calling Foo.</i><br />';
}
document.body.innerHTML += 'About to call Bar.Foo: <br />';
try {
var bar = {};
bar.foo = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(fn){ setTimeout(fn, 1000 / 24); };
bar.foo(function(){ document.body.innerHTML += '<i>Bar.Foo</i><br />'; });
} catch(e){
document.body.innerHTML += '<i> >>> Error thrown when calling Bar.Foo.</i><br />';
}
document.body.innerHTML += foo === bar.foo
? '<strong>Foo and Bar.Foo are considered the same</strong><br />'
: '<strong>Foo and Bar.Foo are NOT considered the same</strong><br />';
body {
font-family: Monaco, 'Courier MS', Coureire, mono-space;
}
嗯,requestAnimationFrame
是 DOM API 的一部分,它不是 JavaScript 对象,所以很难 确定 失败的原因。请记住:
- JavaScript 中的函数在
this
设置为调用者对象的情况下进行分派,在您的情况下,该对象是bar
,它不具有所有属性window
有。 - default 对象 JavaScript 函数是用
window
调度的 - 所以调用window.alert
和alert
是一样的事情(严格模式除外)。
所以,它完全有可能在幕后某处使用 this
。再一次,它是 "Host Object" 所以所有赌注都关闭了。
这是具有相同行为的类似 "plain" JS 代码。
window.msg = "Hello";
function foo(){
if(this !== window) throw new TypeError("Illegal Invocation");
alert(this.msg);
}
foo(); // alerts hello, `this` is window
window.foo(); // alerts hello
var bar = {};
bar.foo = foo;
bar.foo(); // typeerror
解决方法是将其包装在匿名函数中或使用 bind
.
试试这个
var bar = {};
bar.foo = (window.requestAnimationFrame && window.requestAnimationFrame.bind(window)) ||
(window.webkitRequestAnimationFrame && window.webkitRequestAnimationFrame.bind(window)) ||
(window.mozRequestAnimationFrame && window.mozRequestAnimationFrame.bind(window)) ||
(window.msRequestAnimationFrame && window.msRequestAnimationFrame.bind(window)) ||
function(fn){ setTimeout(fn, 1000 / 24); };
bar.foo(function(){ console.log('Bar.Foo') });
这会将 *requestAnimation 的 this
设置为 window 对象
根据@poke 的评论
var bar = {};
bar.foo = (window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(fn){ setTimeout(fn, 1000 / 24); }).bind(window);
bar.foo(function(){ console.log('Bar.Foo') });