Javascript 将对象函数传递给requestAnimationFrame时丢失对象引用
我想知道为什么这些代码变体的行为方式是这样的 第一次设置:Javascript 将对象函数传递给requestAnimationFrame时丢失对象引用,javascript,object,requestanimationframe,Javascript,Object,Requestanimationframe,我想知道为什么这些代码变体的行为方式是这样的 第一次设置: 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 requestAnimati
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
函数时,它就失败了,因为这个在被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();
通过闭包传递run
函数可以解决问题。为什么这会起作用,而前面的示例却不起作用?我的实际代码需要非常高效地运行,我不想在运行循环中使用闭包,因为我不想戳到GC。也许这没什么大不了的?(我最担心的是移动设备)。小提琴:
最后是最后一个按预期运行的案例:
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();
同样出于性能(OCD)原因,如果可以避免,我不希望通过全局引用此对象。小提琴:
有人能给我解释一下为什么第一个例子失败了,以及运行这个循环以尽可能提高内存/GC效率的最佳途径吗
谢谢你抽出时间 传递给requestAnimationFrame
的函数引用在全局上下文中执行(其中此
指浏览器中的窗口
对象)
为了在任何其他作用域中执行传递给requestAnimationFrame的函数引用,您需要对该作用域执行以下操作之一:
requestAnimationFrame(this.run.bind(this));
或者传入一个匿名包装函数,该函数基本上在其原始范围内执行您的函数(这就是您在这里所做的)
太好了,谢谢。就性能而言,一种方法比另一种方法有好处吗?bind
方法与匿名函数的作用基本相同。一个简单得可笑的测试用例说Chrome的V8更喜欢匿名的版本()。不管怎样,我都不担心,它们都是可读性很强的代码行
var self = this;
requestAnimationFrame(function(){ self.run(); });