0

我想我很难理解以下代码的范围:

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();

最终发生的事情是,“滴答”被调用了很多很多次,而 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中的内部函数和对象是否不跟踪其父级的范围和变量?

4

1 回答 1

4

您最初的问题是您在内部调用this.ticksetTimeout

setTimeout(this.tick(), this.time);

相反,您希望传递对函数的引用this.tick

setTimeout(this.tick, this.time);

这解决了第一个循环的问题,但第二次调用tick(来自setTimeout)没有绑定到正确的范围;因此,您可以将函数引用绑定到thisusing的当前值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();
于 2013-05-11T19:31:33.377 回答