2015-09-20 49 views
2

我很尴尬承认我花了多少小时来解决这个问题。事实证明,在“问题区域”注释下的两行命令在原型addSong函数中使用时会更改“this”的上下文。为什么在这个例子中“this”的上下文变化了?

var PlaylistView = function(config){ 

    this.config = config || {}; 
    this.$addSongForm = this.config.addSongForm || $('#addSongForm'); 
    this.$song = this.config.song || $('#song'); 

    // problem area 
    this.addSong = $.proxy(this.addSong, this); 
    this.listenAddSong(); 
    }; 

PlaylistView.prototype.listenAddSong = function(){ 
    this.$addSongForm.on('submit', this.addSong); 
}; 

PlaylistView.prototype.addSong = function(event){ 
    //Here is where I'm getting different context for this 
    var songName = this.$song.val(); 
    //do some stuff... 
    return false; 
}; 

return PlaylistView; 

当两条线路都在显示我得到了我想要的行为顺序:“这首歌$”包含初始化PlaylistView对象时,我已经设置了jQuery选择。但是,当我将订单逆转时,看着Firefox中的检查员显示“this”指的是DOM中的实际表单。 这是为什么?

+0

没有人能确定你的代码中引用了什么'this',因为'this'的值可以用'.apply'或'.bind'或'.call'等来改变。 。 –

回答

3

原因是因为this.addSong !== $.proxy(this.addSong, this)。当您运行$.proxy,然后listenAddSong使用绑定功能,并且this是您的Playlist对象。当您反转订单时,未绑定函数被传递给listenAddSong中的监听器。您与该行的绑定功能取代未绑定功能:

this.addSong = $.proxy(this.addSong, this); 

因此,根据其功能this.addSong点时listenAddSong运行,你要么得到正确的行为,或不正确的行为。

+0

谢谢你这么清楚地解释“为什么”。 – bluesmoke

相关问题