我是封闭式的新手,并且有一个'让我做大多数事情'对javascript的理解,所以我想知道我如何改进以下是我试图拥有一个具有计数器的对象。试图改善/进一步理解。
编辑:以下代码有效,当然......但可能是错误的(是吗?)......我甚至都不知道代码是正确还是错误......我在哪里可以改进......有没有更好的方法在对象/函数中有一个计时器?
function myObj() {
this.outputId = 'div_output1';
this.counter = 0;
this.limit = 10;
this.count = function() {
// reference to self
var me = this;
if (me.doStuff(me)) setTimeout(function() {
me.count();
},1000);
};
this.doStuff = function(me) {
if (me.counter >= me.limit) {
document.getElementById(me.outputId).innerText = 'count reached limit';
return false;
} else {
document.getElementById(me.outputId).innerText = 'count = ' + me.counter;
me.counter += 1;
return true;
}
}
}
//对象的示例用法......
window.onload = function() {
var x = new myObj;
x.outputId = 'div_output2';
x.count();
var y = new myObj;
y.limit = 8;
y.count();
}
答案 0 :(得分:2)
我会在this
上使用闭包仅用于回调函数中的函数调用。对象的其他方法可以像往常一样使用this
。回调需要显式引用该对象,因为它需要“从外部”调用对象方法。但对于被调用的方法,它只是一个普通的函数调用,它可以像往常一样使用隐式this
来访问它的对象。
我通常也会将方法声明从构造函数中移到对象原型中,因为它更清晰,更有效:
function myObj() {
this.outputId = 'div_output1';
this.counter = 0;
this.limit = 10;
}
myObj.prototype.count = function() {
// reference to self
var me = this;
var callback = function() {
me.count();
};
if (this.doStuff())
setTimeout(callback,1000);
}
myObj.prototype.doStuff = function() {
if (this.counter >= this.limit) {
document.getElementById(this.outputId).innerText = 'count reached limit';
return false;
} else {
document.getElementById(this.outputId).innerText = 'count = ' + this.counter;
this.counter += 1;
return true;
}
}
答案 1 :(得分:2)
您正在使用关闭。因为当setTimeout调用你的函数时,'this'将是'Window'对象,你必须创建一个闭包(你通过将'this'赋给我)并访问它。
无论如何,我仍然会以不同的方式编写代码。我会让doStuff调用自己,而不是让它返回true / false然后决定是否再次调用doStuff。
我不喜欢你如何将'this'对象传递给this.doStuff函数。没有必要这样做。要了解“此”在JavaScript中的工作原理,请查看my detailed answer on the subject。
function Counter(opts)
{
this.outputId = opts.outputId || 'div_output1';
this._currentCount = 0;
this.limit = opts.limit || 10;
this.count = function()
{
this.deferDoStuff();
};
this.deferDoStuff = function()
{
var me = this;
setTimeout(function() { me.doStuff(); }, 1000);
};
this.doStuff = function()
{
if(this._currentCount > this.limit)
{
document.getElementById(this.outputId).innerHTML = 'Count limit reached';
return;
}
document.getElementById(this.outputId).innerHTML = 'count = ' + this._currentCount;
this._currentCount++;
this.deferDoStuff();
};
}
用法:
var x = new Counter( { 'outputId' : 'div1' } );
var y = new Counter( { 'outputId' : 'div2' } );
x.count();
y.count();
答案 2 :(得分:0)
我清理代码的一些方法是:
使用封装,即不要只是制作所有变量&功能公开。你有doStuff方法作为公共对象,这意味着任何人都可以调用,而不仅仅是count方法。这也适用于count,limit和outputId。相反,它们应该传递给构造函数。
使引用对象“me”成为类的私有成员,因此不要在方法中设置它。如果您使用call或apply调用方法,则可能会出现问题,因为此上下文已更改。
e.g。
var obj = new myObj();
var otherobj = {};
obj.call.call(otherobj);
如果你有计数,我也会更改内联。你只是在寻找麻烦!!!
if(doStuff())setTimeout(function(){ me.count(); },1000);
以下是包含我所有建议的代码
function myObj(outputId, limit) {
var counter = 0,
me = this;
function doStuff() {
if (counter >= limit) {
document.getElementById(outputId).innerText = 'count reached limit';
return false;
} else {
document.getElementById(outputId).innerText = 'count = ' + counter;
counter += 1;
return true;
}
}
this.count = function() {
if (doStuff()) {
setTimeout(function() {
me.count();
},1000);
}
};
}
答案 3 :(得分:0)
我没有看到任何真正的问题,但我可能会清理一些事情。
me
参数是多余的,因为它始终与this
相同,并且您不需要在闭包中捕获它。我可能会写这样的doStuff:
var outputDiv = document.getElementById(this.outputId);
this.doStuff = function() {
this.counter++;
if (this.counter > this.limit) {
outputDiv.innerText = 'count reached limit';
return false;
}
else {
outputDiv.innerText = 'count = ' + this.counter;
return true;
}
}
这是一个次要的风格,但我认为更明显的是doStuff正在修改计数器,因为它位于函数的开头而不是隐藏在else子句中。此外,在函数外部移动getElementById可以略微减少重复的代码。