将requestAnimationFrame分配给对象变量时键入Error

时间:2015-07-20 10:36:54

标签: javascript typeerror requestanimationframe

当我尝试创建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') });

即使windowwindow.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> &gt;&gt;&gt; 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> &gt;&gt;&gt; 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;
}

2 个答案:

答案 0 :(得分:1)

好吧,requestAnimationFrame是DOM API的一部分,它不是JavaScript对象,因此很难确定它失败的原因。请记住:

  • 调用JavaScript中的函数,并将this设置为调用者对象,在您的情况下,该对象为bar且没有window所有属性。
  • 默认对象使用window调度JavaScript函数 - 因此调用window.alertalert是一回事(严格模式除外)。

因此,在某处使用this的幕后完全可能。然后,它又是一个主机对象&#34;所以所有赌注都已关闭。

这是类似的&#34;普通&#34; JS代码具有相同的行为。

&#13;
&#13;
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
&#13;
&#13;
&#13;

解决方法是将其包装在匿名函数中或使用bind

答案 1 :(得分:1)

试试这个

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到窗口对象

根据@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') });