首先,我是面向对象的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)); */

07-24 09:43
查看更多