tan*_*rwj 4 javascript oop prototype
我最近一直在努力制作更干净的Javascript代码,并使用原型等对象.但我对某些方面感到困惑......
function TimeCard(){
this.date = new Date();
this.pay_period_begin = null;
this.pay_period_end = null;
}
Run Code Online (Sandbox Code Playgroud)
这是我的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();
}
...
};
Run Code Online (Sandbox Code Playgroud)
我的问题是当我试图调用this.getTimeCardData()它时说我的对象没有这样的方法.我显然可以访问其他变量,因为它们是在我的构造函数中声明的,但我不明白我猜的原型范围.到目前为止,我已经通过解决此得到tc.getTimeCardData()代替this.getTimeCardData(),与tc是我对象的实例对外宣称- var tc = new TimeCard();.我敢肯定,这不是正确的方法,但是这是什么?
我的问题是当我试图调用
this.getTimeCardData()它时说我的对象没有这样的方法.
听起来好像this不再是指您的实例了.你必须向我们展示我们确实要求的实际调用,但是在JavaScript中,this主要是通过如何调用函数来设置,而不是在它定义的位置,因此this最终变得不同的东西相当容易.
这是一个假设的例子:
TimeCard.prototype = {
// ...
doSomething: function() {
// here, `this` probably refers to the timecard
someArray.forEach(function() {
this.getTimeCardData(); // <=== Problem, `this` has changed
});
}
// ...
};
Run Code Online (Sandbox Code Playgroud)
如果我呼叫this.doSomething();一个TimeCard对象,则在呼叫this中将引用时间卡.但在forEach回调中,this将不再引用时间卡.所有类型的回调都会发生同样的变化; 阿贾克斯等
要解决它,你可以记住this一个变量:
TimeCard.prototype = {
// ...
doSomething: function() {
var thisCard = this;
someArray.forEach(function() {
thisCard.getTimeCardData(); // <=== Problem
});
}
// ...
};
Run Code Online (Sandbox Code Playgroud)
根据您的具体情况,还有其他各种方法可以解决这个问题.例如,你有selectAll电话getTimeCardData.但是假设selectAll用错误的this值调用?在你的评论中,你说你这样做:
$('#container').on('click', '#selectAll', tc.selectAll);
Run Code Online (Sandbox Code Playgroud)
这意味着selectAll调用时,this将引用DOM元素,而不是对象.
在这种特定情况下,您有三种选择:
由于你正在使用jQuery,你可以使用$.proxy它接受一个函数和一个值来使用this,并返回一个新的函数,当被调用时,它将调用this设置为所需值的原始函数:
$('#container').on('click', '#selectAll', $.proxy(tc.selectAll, tc));
Run Code Online (Sandbox Code Playgroud)使用ES5 Function#bind,它做同样的事情.请注意IE8及更早版本没有它,除非你包含一个"ES5垫片"(因此我$.proxy在上面注意到;你知道你有这个):
$('#container').on('click', '#selectAll', tc.selectAll.bind(tc));
Run Code Online (Sandbox Code Playgroud)使用闭包(不要让名字打扰你,闭包不复杂):更多(在我的博客上):
$('#container').on('click', '#selectAll', function() {
tc.selectAll();
});
Run Code Online (Sandbox Code Playgroud)在上述所有情况中,您将失去this引用DOM元素的好处.在这种特殊情况下,您可能并不关心,但如果您这样做,则可以从事件对象的currentTarget属性中获取它.举例来说,这就要求tc.selectAll有this提及tc和传递什么会一直this(DOM元素,你勾搭上的处理程序)作为第一个参数:
$('#container').on('click', '#selectAll', function(e) {
tc.selectAll(e.currentTarget);
});
Run Code Online (Sandbox Code Playgroud)
另一种不太可能的可能性与您的更新方式有关TimeCard.prototype.你正在这样做的方式,可以new TimeCard() 在替换TimeCard.prototype对象的代码运行之前创建对象,这意味着他们将拥有旧的原型.
一般来说,我强烈建议不要替换为prototype构造函数的属性自动创建的对象.相反,只需添加到已存在的对象,如下所示:
function TimeCard(){
this.date = new Date();
this.pay_period_begin = null;
this.pay_period_end = null;
}
TimeCard.prototype.getTimeCardData = function(){
//ajax request
};
// ...
Run Code Online (Sandbox Code Playgroud)
原因如下:时间.如果替换属性上的对象,则在执行替换之前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;
})();
Run Code Online (Sandbox Code Playgroud)
......主要是因为它可以防止时间问题.
| 归档时间: |
|
| 查看次数: |
6651 次 |
| 最近记录: |