创建新对象后,如何防止旧对象丢失?

How do I prevent loss of older objects, after I create a new one?

我会尽可能简单地解释一下。

我正在尝试制作一个计时器应用程序来练习。用户应该能够添加一个新的对象,它将是一个计时器 + stop/start 个按钮。

此时,它正在处理一个对象,但是当我创建另一个对象时,旧对象停止工作(我相信它失去了指向它的指针,或类似的东西),而新对象开始工作。

别担心,关于按钮功能,这并不重要,我只想了解如何在创建新对象后保存对象。

这是 JS:

var startTime = 0;
var itemNum = 0;
var obName;
var arrayForTimers = [];

function timerObject(obName) {
this.nameField = "start";
this.classField = "timer";
this.block = " ";
this.obName = obName;
this.startButton = " ";
this.stopButton = " ";
this.placeholder = document.getElementsByClassName("timer-placeholder")[0];
this.addBlock = function () {
    this.block = document.createElement("DIV");
    this.block.className = this.classField;
    this.block.className += " " + this.obName;
    this.placeholder.appendChild(this.block);
}
this.renderTime = function () {
    this.startTime = startTime;
    this.endTime = new Date();
    // time difference in ms
    this.timeDiff = this.endTime - this.startTime;
    // strip the miliseconds
    this.timeDiff /= 1000;
    // get seconds
    this.seconds = Math.round(this.timeDiff % 60);
    // remove seconds from the date
    this.timeDiff = Math.floor(this.timeDiff / 60);
    // get minutes
    this.minutes = Math.round(this.timeDiff % 60);
    // remove minutes from the date
    this.timeDiff = Math.floor(this.timeDiff / 60);
    // get hours
    this.hours = Math.round(this.timeDiff % 24);
    this.block.innerHTML = this.hours + " h " + this.minutes + " min " + this.seconds + " sec";
    // window.setInterval('this.obName.renderTime()',1000);// Uncomment if you want to test your PCs limit
}
this.renderButtons = function () {
    var timePassed;
    //this.parentTimer = document.getElementsByClassName("timer "+this.obName)[0];
    this.startButton = document.createElement("INPUT");
    this.startButton.setAttribute("type", "button");
    this.startButton.setAttribute("value", "start");
    this.startButton.className = "start " + this.obName;
    this.stopButton = document.createElement("INPUT");
    this.stopButton.setAttribute("type", "button");
    this.stopButton.setAttribute("value", "stop");
    this.stopButton.className = "stop " + this.obName;
    this.placeholder.insertBefore(this.startButton, this.block);
    this.placeholder.insertBefore(this.stopButton, this.block);
    this.startButton.addEventListener("click", function () {
        //if (this.hours === 0 && this.minutes === 0 && this.seconds === 0){
        this.startTime = new Date();
        // }
        tm = window.setInterval('obName.renderTime()', 1000);
    })
    this.stopButton.addEventListener("click", function () {
        window.clearInterval(tm);
        //timePassed = this.endTime - this.startTime;

        //endTime = new Date();
        // timePassed = endTime - startTime;
    })
    //give listener to clear and start interval
    }
};

function createNewTimer() {
    obName = document.getElementById("ObName").value;
    if (obName !== "") {
       obName = new timerObject(obName);
       obName.addBlock();
       obName.renderButtons();
       startTime = new Date();
        obName.renderTime();
        //arrayForTimers.push(obName);
       //window.setInterval('obName.renderTime()',1000);
     } else {
       document.getElementById("ObName").value = "Fill me";
   }
};

这里有一个JsFiddlehttp://jsfiddle.net/3qxoea52/4/

P.S。对不起我的语法,不是我的母语。

谢谢。

问题就在这里

tm = window.setInterval('obName.renderTime()', 1000);

这意味着当您单击任何启动按钮时,它将始终启动当前与 obName 关联的对象。

此外,您只有一个全局变量 tm 来存储计时器,所以当您这样做时

window.clearInterval(tm);

正在清除上次设置的定时器。

而且您还有一个全局 startTime,这会导致所有计时器在您创建新计时器时重置。

另一个问题是当你停止每个定时器时,你没有任何东西来存储时间,所以如果你停止然后重新启动它,它不会在同一点继续。

您可以通过以下方式解决这些问题:

  1. 使用self = this创建对象的稳定引用
  2. 使用 function.bind 确保事件处理程序将绑定到正确的计时器对象
  3. 添加一个属性 this.startDiff 以便在您停止然后重新启动时钟时保存时间
  4. 使 tm 成为 TimerObject
  5. 中的局部变量
  6. 在对象内而不是在对象外设置 this.startTime

-- 如以下代码所示 (jsfiddle)

function TimerObject(obName) {
    var self = this,
        tm;
    this.startTime = new Date();
    this.startDiff = 0;
    this.nameField = "start";
    this.classField = "timer";
    this.block = " ";
    this.obName = obName;
    this.startButton = " ";
    this.stopButton = " ";
    this.placeholder = document.getElementsByClassName("timer-placeholder")[0];
    this.addBlock = function () {
        this.block = document.createElement("DIV");
        this.block.className = this.classField;
        this.block.className += " " + this.obName;
        this.placeholder.appendChild(this.block);
    };
    this.renderTime = function () {
        var timeDiff = new Date() - this.startTime + this.startDiff;
        this.timeDiff = timeDiff;
        timeDiff /= 1000;
        // get seconds
        this.seconds = Math.round(timeDiff % 60);
        // remove seconds from the date
        timeDiff = Math.floor(timeDiff / 60);
        // get minutes
        this.minutes = Math.round(timeDiff % 60);
        // remove minutes from the date
        timeDiff = Math.floor(timeDiff / 60);
        // get hours
        this.hours = Math.round(timeDiff % 24);
        this.block.innerHTML = this.hours + " h " + this.minutes + " min " + this.seconds + " sec";
        // window.setInterval('this.obName.renderTime()',1000);// Uncomment if you want to test your PCs limit
    };
    this.renderButtons = function () {
        var timePassed;
        //this.parentTimer = document.getElementsByClassName("timer "+this.obName)[0];
        this.startButton = document.createElement("INPUT");
        this.startButton.setAttribute("type", "button");
        this.startButton.setAttribute("value", "start");
        this.startButton.className = "start " + this.obName;
        this.stopButton = document.createElement("INPUT");
        this.stopButton.setAttribute("type", "button");
        this.stopButton.setAttribute("value", "stop");
        this.stopButton.className = "stop " + this.obName;
        this.placeholder.insertBefore(this.startButton, this.block);
        this.placeholder.insertBefore(this.stopButton, this.block);
        this.startButton.addEventListener("click", function () {
            //if (this.hours === 0 && this.minutes === 0 && this.seconds === 0){
            self.startTime = new Date();
            // }
            tm = window.setInterval(self.renderTime.bind(self), 1000);
        });
        this.stopButton.addEventListener("click", function () {
            window.clearInterval(tm);
            self.startDiff = self.timeDiff;
            console.log(':', self, self.startDiff);
            //timePassed = this.endTime - this.startTime;

            //endTime = new Date();
            // timePassed = endTime - startTime;
        });
        //give listener to clear and start interval
    };
}


function createNewTimer() {
    obName = document.getElementById("ObName").value;
    if (obName !== "") {
        obName = new TimerObject(obName);
        obName.addBlock();
        obName.renderButtons();
        obName.renderTime();
        //window.setInterval('obName.renderTime()',1000);
    } else {
        document.getElementById("ObName").value = "Fill me";
    }
}

代码存在几个问题: 1. 一些函数没有绑定到正确的上下文 (this)。 2. 设置为 "obName" 的引用是全局的,并且不断变化到新创建的实例。 3.开始时间变量是全局变量,每次调用renderTime函数时都会不断重置。

我已经在 jsFiddle 中对您的代码进行了修改,可以在本次更新中找到它们:http://jsfiddle.net/3qxoea52/5/

渲染:

this.renderTime = function (startTime) {
    if( startTime ) {
        this.startTime = startTime;
    }
    this.endTime = new Date();
    // time difference in ms
    this.timeDiff = this.endTime - this.startTime;
    // strip the miliseconds
    this.timeDiff /= 1000;
    // get seconds
    this.seconds = Math.round(this.timeDiff % 60);
    // remove seconds from the date
    this.timeDiff = Math.floor(this.timeDiff / 60);
    // get minutes
    this.minutes = Math.round(this.timeDiff % 60);
    // remove minutes from the date
    this.timeDiff = Math.floor(this.timeDiff / 60);
    // get hours
    this.hours = Math.round(this.timeDiff % 24);
    this.block.innerHTML = this.hours + " h " + this.minutes + " min " + this.seconds + " sec";
    // window.setInterval('this.obName.renderTime()',1000);// Uncomment if you want to test your PCs limit
}

绑定:

this.startButton.addEventListener("click", function () {
            //if (this.hours === 0 && this.minutes === 0 && this.seconds === 0){
            this.startTime = new Date();
            // }
            this.tm = window.setInterval(this.renderTime.bind(this), 1000);
        }.bind(this))
        this.stopButton.addEventListener("click", function () {
            window.clearInterval(this.tm);
            //timePassed = this.endTime - this.startTime;

            //endTime = new Date();
            // timePassed = endTime - startTime;
        }.bind(this))

创建定时器:

function createNewTimer() {
    obName = document.getElementById("ObName").value;
    if (obName !== "") {
        obName = new timerObject(obName);
        obName.addBlock();
        obName.renderButtons();
        startTime = new Date();
        obName.renderTime(startTime);
        //window.setInterval('obName.renderTime()',1000);
    } else {
        document.getElementById("ObName").value = "Fill me";
    }
};