Javascript多个原型函数-如何从一个调用另一个
最近,我一直在努力制作更干净的Javascript代码,并将对象与原型一起使用等等。但我对一些问题感到困惑Javascript多个原型函数-如何从一个调用另一个,javascript,oop,prototype,Javascript,Oop,Prototype,最近,我一直在努力制作更干净的Javascript代码,并将对象与原型一起使用等等。但我对一些问题感到困惑 function TimeCard(){ this.date = new Date(); this.pay_period_begin = null; this.pay_period_end = null; } 这是我的timecard对象,带有一些初始值。我有一大堆我已经写过的函数,还有更多的函数,它们是时间卡的一部分,如
function TimeCard(){
this.date = new Date();
this.pay_period_begin = null;
this.pay_period_end = null;
}
这是我的timecard对象,带有一些初始值。我有一大堆我已经写过的函数,还有更多的函数,它们是时间卡的一部分,如果我理解正确的话,它们将是原型函数。以下是我目前掌握的一些信息:
TimeCard.prototype = {
init : function(){
this.pay_period_begin = $("#pay_period_begin");
this.pay_period_end = $("#pay_period_end");
},
getTimeCardData : function(){
//ajax request
},
selectAll : function(){
this.getTimeCardData();
}
...
};
我的问题是,当我尝试调用this.getTimeCardData()
时,它说我的对象没有这样的方法。很明显,我可以访问其他变量,因为它们是在我的构造函数中声明的,但我不理解原型的作用域是如何定义的。到目前为止,我已经通过使用tc.getTimeCardData()
而不是this.getTimeCardData()
解决了这个问题,其中tc
是我在外部声明的对象的实例-var tc=new TimeCard()代码>。我确信这不是正确的方法,但什么是正确的
我的问题是,当我尝试调用this.getTimeCardData()
时,它说我的对象没有这样的方法
听起来好像这个
不再引用您的实例。当然,您必须向我们展示实际的调用,但是在JavaScript中,这个
主要是通过调用函数的方式来设置的,而不是通过定义函数的位置来设置的,因此,这个
很容易变成不同的东西
下面是一个假设的例子:
TimeCard.prototype = {
// ...
doSomething: function() {
// here, `this` probably refers to the timecard
someArray.forEach(function() {
this.getTimeCardData(); // <=== Problem, `this` has changed
});
}
// ...
};
根据您的具体情况,还有其他各种解决方法。例如,您有selectAll
调用getTimeCardData
。但是,假设调用selectAll
时使用了错误的此
值?在你的评论中,你说你是这样做的:
$('#container').on('click', '#selectAll', tc.selectAll);
function TimeCard(){
this.date = new Date();
this.pay_period_begin = null;
this.pay_period_end = null;
}
TimeCard.prototype.getTimeCardData = function(){
//ajax request
};
// ...
这意味着当调用selectAll
时,this
将引用DOM元素,而不是对象
在这种特定情况下,您有三种选择:
由于您使用的是jQuery,因此可以使用$.proxy
,它接受一个函数和一个值作为this
,并返回一个新函数,调用该函数时,将调用原始函数,并将this
设置为所需值:
$('#container').on('click', '#selectAll', $.proxy(tc.selectAll, tc));
使用ES5的函数#bind
,它做同样的事情。请注意,IE8和更早版本没有它,除非您包括一个“ES5垫片”(因此我在上面提到了$.proxy
,您知道您有):
使用闭包(不要让名称困扰您,闭包并不复杂):
更多(在我的博客上):
在上述所有情况下,您将失去引用DOM元素的这个的好处。在这种特殊情况下,您可能不在乎,但如果在乎,您可以从事件对象的currentTarget
属性中获得它。例如,这将调用tc。使用this
引用tc
并将本应是this
的内容(钩住处理程序的DOM元素)作为第一个参数选择All
:
$('#container').on('click', '#selectAll', function(e) {
tc.selectAll(e.currentTarget);
});
另一个不太可能的可能性与您如何更新TimeCard.prototype
有关。按照您的方式,可以在替换TimeCard.prototype的代码运行之前,通过new TimeCard()
创建对象,这意味着它们将拥有旧的原型
通常,我强烈建议不要替换为构造函数的prototype
属性自动创建的对象。相反,只需添加到已经存在的对象,如下所示:
$('#container').on('click', '#selectAll', tc.selectAll);
function TimeCard(){
this.date = new Date();
this.pay_period_begin = null;
this.pay_period_end = null;
}
TimeCard.prototype.getTimeCardData = function(){
//ajax request
};
// ...
原因如下:时间。如果在prototype
属性上替换对象,则在替换之前通过new TimeCard()
创建的任何对象都将使用旧原型,而不是新原型
我还建议始终在作用域函数中创建这些,以便您知道声明和原型添加同时发生:
var TimeCard = (function() {
function TimeCard(){
this.date = new Date();
this.pay_period_begin = null;
this.pay_period_end = null;
}
TimeCard.prototype.getTimeCardData = function(){
//ajax request
};
// ...
return TimeCard;
})();
…主要是因为它可以防止计时问题。您能告诉我们调用this.getTimeCardData()的函数吗?是的,它已经在selectAll
函数下显示的代码中了。@theourtheye:谢谢。是的。事实上,人们确实如此。:-)右上角有一个RSS提要链接,但是如果你只是把地址发进去,任何体面的读者都会自动发现。给我写张便条,告诉我你有什么问题?tj。crowder@farsightsoftware.comepic答案和往常一样,汉克斯,我开始明白了。虽然这两个都不是我的问题,但我认为我所指的实际调用只是在原型中的selectAll
函数中。因此,由于某种原因,这些原型无法看到对方。但我很喜欢你最后给出的例子,我必须试试。@Tanner:这可能把问题推到了一个层次:调用selectAll
的方式如何?因为如果selectAll
被用作回调(事件处理程序、ajax处理程序、setTimeout
回调等),那么在调用selectAll
的过程中,this
将不再指向对象。@Tanner:十有八九,您已经有了一个有用的上下文可以关闭,所以我倾向于这样。但如果你没有,我可能倾向于使用垫片和函数#bind
。但在这一点上,它基本上是一种风格。
var TimeCard = (function() {
function TimeCard(){
this.date = new Date();
this.pay_period_begin = null;
this.pay_period_end = null;
}
TimeCard.prototype.getTimeCardData = function(){
//ajax request
};
// ...
return TimeCard;
})();