正确访问范围之外的实例并模拟多个实例

时间:2015-12-13 02:44:27

标签: javascript scope templating

我已经在我的jsfiddle(http://jsfiddle.net/cjros/2xuxb2kp/)上做了一些笔记,正如你所看到的那样,我有一个带有几种方法的Timer模型。

var TimerModel = function (timerName, startTimerLimit) {

this._init = function () {
    this.setTimerName(timerName);
    this.startTimerLimit = startTimerLimit * 1000; // in milliseconds
    this.setInitialTimerDisplay(startTimerLimit);
    this.isTimerActive = false;
};

this.setTimerName = function (timerName) {
    $('#display-timer-name').html(timerName);
};

this.setInitialTimerDisplay = function (timerLimit) {
    $('#display-timer-limit').html(timerLimit);
};

this.startTimer = function () {
    this.isTimerActive = true;
    var startingCountdown = setInterval(function () {
        if (this.startTimerLimit === 0 && this.isTimerActive) {
            clearInterval(startingCountdown);
            this.isTimerActive = false;
            alert('Time is up!');
        } else {
         this.startTimerLimit -= 1000;
         $('#display-timer-limit').html(this.startTimerLimit / 1000);
        }
    }.bind(this), 1000);
};

this.pauseTimer = function () {
    if (this.isTimeActive) { 
        clearInterval(/* how would i access this.startTimer()'s setInterval? */) 
    };
};

this._init(); 

}

$('#start-timer').click(function () {
    var timerName = $('#set-timer-name').val();
    var initTime = parseInt($('#set-timer-limit').val());
    var timer = new TimerModel(timerName, initTime);
    timer.startTimer();
});

$('#pause-timer').click(function() {
    // how would I properly access my 'timer' instance that I created in the '#start-timer' action event?
});
  • 我想知道如何访问我在开始按钮点击事件中创建的实例(第48行)。如果你在我的暂停按钮点击事件上看起来稍微低一点,我正在试图找出如何访问同一个实例,但不一定知道如何做到这一点。

  • 我的另一个问题是尝试访问或与Timer模型中的另一种方法“通信”。正如您在第39行看到的那样,我正在尝试从this.startTimer方法中清除异常,但实际上并不知道如何访问该函数/变量。

  • 关于javascript知识的更广泛说明,我的代码格式是否是创建模型(类)的正确方法?有没有人有我应该阅读的任何其他建议,或者考虑格式化我的代码以使其更容易并避免我上面遇到的一些问题?

    • 我想知道的另一个重要问题是:如果我想创建多个此计时器模型的实例,以便我可以单独启动/停止/暂停每个实例,该怎么办?我该如何考虑现在格式化此代码?我是否需要超类或其他东西来监控所有这些实例?这是模板出现的地方(绝对不能有多个相同的DOM元素id)?我知道如何通过创建viewModel并将它们模板化来实现这一点;我只是想更好地理解如何本地执行此操作(jQuery被用作例外)。

非常感谢提前的帮助。非常值得学习!

1 个答案:

答案 0 :(得分:0)

看起来您可能需要深入研究JavaScript范围。只要函数存在,在函数访问范围内创建的对象/变量将保留在范围内。例如,如果在TimerModel的主体中创建区间变量,则可以在整个函数中使用。

var TimerModel = function (timerName, startTimerLimit) {
    var startingCountdown = null;

    this.startTimer = function () {
        this.isTimerActive = true;
        startingCountdown = setInterval(
        //......
    };

    //And it can be easily cancelled later
    this.cancelTimer = function() {
        clearInterval(startingCountdown);
    };
};

所以你创建了一个变量var tm = new TimerModel("test", 20);。 只要存在变量tm,对象实例中的函数/方法就能够访问startingCountdown

至于存储对象,我要提到的一个小jQuery技巧是$.data()函数。 $.data()是一种将任意数据存储到DOM中的元素的方法。示例用法是:

var el = $("someSelector");
var tval = parseInt(el.val());
var tm = new TimerModel("test", tval);
el.data("timer", tm);

现在对象tm存储在DOM中。要在以后检索它:

var tm = $("someSelector").data("timer");

或者您可以执行类似存储计时器名称的操作:

el.data("timerName", "testTimer");
var timerName = el.data("timerName");

我上面提到的范围内容也适用于jQuery。因此,在准备好的脚本中,您创建的任何变量都可以通过以下函数使用:

$(document).ready(function() {

    //Create a variable to hold the timer
    var timer = null;

    $('#start-timer').click(function () {
        var timerName = $('#set-timer-name').val();
        var initTime = parseInt($('#set-timer-limit').val());

        //Create the timer on the variable, or maybe see if the user wants
        // to cancel the timer if it already exists.
        if (timer) {
            if (confirm("Cancel the current timer?")) {
                timer.destroy(); //<==assumes this method is created.
                timer = null;
            } else {
                return;
            }
        }

        timer = new TimerModel(timerName, initTime);
        timer.startTimer();
    });

    $('#pause-timer').click(function() {
        if (timer) timer.pause();
    });
});

如果你想把这个想法提升一个档次,并希望能够创建任意数量的计时器,那么你最好创建一个处理计时器的对象。您已经使用了一些计时器名称。您可以为现有的TimerModel添加名称属性。

var TimerModel = function (timerName, startTimerLimit) {
    this.name = timerName;
};

因此您可以稍后通过名称访问计时器。

var TimerModelCollection = function() {
    var timers = [];

    this.addTimer = function(name, time) {
        var tm = new TimerModel(name, time);
        timers.push(tm);
        return tm;
    };

    //Other methods to remove timers, and such, as well as a way to access
    // them by name would be needed too.
    this.getByName = function(name) {
        for(var i in timers)
            if (timers[i].name == name) 
                return timers[i];
        return null;
    };

    //etc, etc...
};

使用上面提到的一些其他方法,您可以弄清楚如何创建计时器,保存它们或它们的名称以便以后检索。

希望这有帮助!