首先,我是面向对象JS的新手,但对JS和jQuery很有经验。
我遇到的问题毫无意义,在代码中有更好的解释,请参阅下文:
var $table = $("tbody#peopleContainer"); // hypothetical table to which we will append rows for each person object
var Person = function( name ) { //nothing special here
this.name = name;
this.nickname = "";
}
Person.prototype = {
create: function() {
$tr = $table.append("<tr></tr>"); //create a blank row
this.$name = $('<td>'+this.name+'</td>').appendTo( $tr );
this.$nickname = $('<td><input type="text"></td>').appendTo( $tr );
$table.append( this.$td ).append( this.$nickname );
self = this;
this.$name.on("click", $.proxy(self.logName, self)); // logs the name of the person's row you clicked
$("input", this.$nickname).change(function() { // Should log the nickname you typed as well as the person's name whose nickname you changed
self.nickname = $(this).val();
$.proxy(self.logNameAndNickname, self)(); // Problem! Logs the nickname you typed in, but ALWAYS logs the last instantiated person's name
})
},
logName: function() {
console.log(this.name);
},
logNameAndNickname: function() {
console.log(this.name, this.nickname); // for some reason this.name returns the last instantiated person's name (Person #0).
}
}
// create 100 people and append to table
x = 100;
while ( x-- > 0 ) {
person = new Person("Person #"+x);
person.create();
}
由于某种原因,logName()
会记录正确的人的姓名,但logNameAndNickname()
始终记录最后一个实例化的人的姓名,尽管它会记录正确的昵称。好像this
引用了同一范围内的2个独立对象。
所以我的问题是 - 这里发生了什么?
后续问题:这是将jQuery事件与对象一起使用的正确方法吗?我是面向对象JS的新手,所以请告诉我是否有更合适的方法来完成同样的事情。
答案 0 :(得分:1)
问题在于
1)self
是一个全局变量(用var
关键字定义),每次创建一个Person时都会被“覆盖”。
2)然后您代理logName
和logNameAndNickname
,将这些函数中的this引用替换为self
,这将始终引用 last 创建的人员
答案 1 :(得分:0)
self
是一个无意中的全局变量,它将被每个构造函数覆盖,然后在while循环之后保存最后一个实例。您需要将其设置为构造函数范围的本地。
此外,如果您使用$.proxy
,那么 需要使用self
,如果您使用self
则 >需要使用$.proxy
。
this.$name.on("click", $.proxy(this.logName, this));
/* is equivalent to
var self = this;
this.$name.on("click", function() {
self.logName()
}); */
var self = this;
this.$nickname.find("input").change(function() {
self.nickname = $(this).val();
self.logNameAndNickname();
});
/* or
this.$nickname.find("input").change($.proxy(function(e) {
this.nickname = e.target.value;
this.logNameAndNickname();
}, this)); */