我认为我很难绕过以下代码的范围:
var EventEmitter = require('events').EventEmitter, util = require('util');
// Here is the Ticker constructor:
var Ticker = function(time) {
this.time = time;
this.tick = function() {
this.emit('tick');
setTimeout(this.tick(), this.time);
};
}
util.inherits(Ticker, EventEmitter);
var newTicker = new Ticker(1000);
newTicker.on('tick', function() { console.log("TICK"); });
newTicker.tick();
最终发生的事情是,“tick”被调用多次,多次填充堆栈而没有setTimeout实际将超时设置为一秒。
可以向我解释发生了什么事吗?
编辑:我看起来多一点,我仍然无法弄清楚范围问题,真的。
我最终做的是遵循为问题提供的解决方案,我试图通过setTimeout()来解决。
给出的解决方案是:
var EventEmitter = require('events').EventEmitter, util = require('util');
// Here is the Ticker constructor:
var Ticker = function(time) {
var self = this;
this.time = time;
setInterval(function() {
self.emit('tick');
}, self.time);
};
util.inherits(Ticker, EventEmitter);
var ticker = new Ticker(1000);
ticker.on('tick', function() { console.log("TICK"); });
这对我来说更有意义......我现在想知道的是:javascript中的内部函数和对象是不是跟踪其父级的范围和变量?
答案 0 :(得分:4)
您最初的问题是您在this.tick
内呼叫 setTimeout
:
setTimeout(this.tick(), this.time);
相反,您希望将引用传递给this.tick
函数:
setTimeout(this.tick, this.time);
这解决了第一个循环的问题,但是对tick
的第二次调用(来自setTimeout
)没有绑定到正确的范围;因此,您可以使用this
将函数引用绑定到bind
的当前值:
setTimeout(this.tick.bind(this), this.time);
(如果您愿意,也可以使用self
技巧。)
所以,完整的工作计划是:
var EventEmitter = require('events').EventEmitter, util = require('util');
// Here is the Ticker constructor:
var Ticker = function(time) {
this.time = time;
this.tick = function() {
this.emit('tick');
setTimeout(this.tick.bind(this), this.time);
};
}
util.inherits(Ticker, EventEmitter);
var newTicker = new Ticker(1000);
newTicker.on('tick', function() { console.log("TICK"); });
newTicker.tick();