首先,我是面向对象的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的新手,所以请告诉我是否有一种更合适的方法来完成同一件事。
最佳答案
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)); */