将对象函数传递给 requestAnimationFrame 时丢失对象引用
Losing object reference when passing object function to 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 requestAnimationFrame?
requestAnimationFrame(this.run);
this.test();
},
init: function(){
this.div = document.getElementById('output');
this.run();
}
};
a.init();
我希望这个可以工作,但是一旦 requestAnimationFrame
开始调用 run
函数就失败了,因为 this
在被 [=13= 调用时引用 Window
]. Fiddle: http://jsfiddle.net/titansoftime/gmxourcq/
这个有效:
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。也许这没什么大不了的? (我主要担心移动设备)。 Fiddle: http://jsfiddle.net/titansoftime/Lqhcwoyu/
最后一个按预期工作的案例:
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) 原因,如果可以避免,我宁愿不通过全局引用此对象。 Fiddle: http://jsfiddle.net/titansoftime/5816fLxe/
有人可以向我解释第一个示例失败的原因以及关于 运行 使此循环尽可能 memory/GC 高效的最佳方法吗?
感谢您的宝贵时间。
传递给 requestAnimationFrame
的函数引用在全局上下文中执行(其中 this
指的是浏览器中的 window
对象)。
为了在任何其他范围内执行传递给 requestAnimationFrame 的函数引用,您需要 bind the function reference 到该范围:
requestAnimationFrame(this.run.bind(this));
或者传入一个匿名包装函数,它基本上在它的原始范围内执行你的函数(这就是你在这里所做的)。
var self = this;
requestAnimationFrame(function(){ self.run(); });
我想知道为什么这些代码变体会以它们的方式运行。
首次设置:
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
在被 [=13= 调用时引用 Window
]. Fiddle: http://jsfiddle.net/titansoftime/gmxourcq/
这个有效:
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。也许这没什么大不了的? (我主要担心移动设备)。 Fiddle: http://jsfiddle.net/titansoftime/Lqhcwoyu/
最后一个按预期工作的案例:
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) 原因,如果可以避免,我宁愿不通过全局引用此对象。 Fiddle: http://jsfiddle.net/titansoftime/5816fLxe/
有人可以向我解释第一个示例失败的原因以及关于 运行 使此循环尽可能 memory/GC 高效的最佳方法吗?
感谢您的宝贵时间。
传递给 requestAnimationFrame
的函数引用在全局上下文中执行(其中 this
指的是浏览器中的 window
对象)。
为了在任何其他范围内执行传递给 requestAnimationFrame 的函数引用,您需要 bind the function reference 到该范围:
requestAnimationFrame(this.run.bind(this));
或者传入一个匿名包装函数,它基本上在它的原始范围内执行你的函数(这就是你在这里所做的)。
var self = this;
requestAnimationFrame(function(){ self.run(); });