我想知道为什么这些代码变体的行为方式如此。
首次设置:
var a = {
val: 23,
div: null,
test: function(){
this.div.innerHTML = this.div.innerHTML + ' ' + this.val;
},
run: function(){
// why is "this" the window object here when called by requestAnimationFrame?
requestAnimationFrame(this.run);
this.test();
},
init: function(){
this.div = document.getElementById('output');
this.run();
}
};
a.init();
我希望这项工作有效,但requestAnimationFrame
开始调用run
函数this
时,Window
在requestAnimationFrame
调用var a = {
val: 23,
div: null,
test: function(){
this.div.innerHTML = this.div.innerHTML + ' ' + this.val;
},
run: function(){
var self = this;
requestAnimationFrame(function(){ self.run(); });
this.test();
},
init: function(){
this.div = document.getElementById('output');
this.run();
}
};
a.init();
时就会失败。小提琴:http://jsfiddle.net/titansoftime/gmxourcq/
这个有效:
run
通过闭包传递var a = {
val: 23,
div: null,
test: function(){
this.div.innerHTML = this.div.innerHTML + ' ' + this.val;
},
run: function(){
requestAnimationFrame(a.run);
a.test();
},
init: function(){
this.div = document.getElementById('output');
this.run();
}
};
a.init();
函数解决了这个问题。为什么这个工作而不是前面的例子有效?我的实际代码需要非常有效地运行,我宁愿不在运行循环中使用闭包,因为我不想戳GC。也许这不是什么大不了的事? (我最担心的是移动设备)。小提琴:http://jsfiddle.net/titansoftime/Lqhcwoyu/
最后,最后一个案例按预期运作:
{{1}}
再次出于性能(OCD)的原因,我宁愿不通过全局引用此对象,如果我可以避免它。小提琴:http://jsfiddle.net/titansoftime/5816fLxe/
有人可以向我解释为什么第一个例子失败了,并且最好的方法是尽可能高效地运行这个循环作为内存/ GC吗?
感谢您的时间。
答案 0 :(得分:2)
传递给requestAnimationFrame
的函数引用在全局上下文中执行(其中this
在浏览器中引用window
对象。)
为了执行在任何其他范围内传递给requestAnimationFrame的函数引用,您需要bind the function reference到该范围:
requestAnimationFrame(this.run.bind(this));
或传入一个匿名包装函数,它基本上在它的原始范围内执行你的函数(这就是你在这里所做的)。
var self = this;
requestAnimationFrame(function(){ self.run(); });