我有一个动态生成的页面,其中包含一定数量(用户动态定义)的高级散点图。我打算创建一个定义散点图本身的JavaScript对象,即获取一些参数,一些数据和一些容器ID,并创建获取可视化所需的各种元素:canvas元素,工具栏等。这样做,我开始使用以下(简化)类:
(function () {
if (!this.namespace) { this.namespace = {};}
this._instances = { index: 0 };
this.namespace.ScatterPlot = function (containerId, file, options) {
_instances.index ++;
this.id = this.containerId+"-"+_instances.index ;
this.containerId = containerId ;
_instances [this.id] = this;
// ... Do stuffs with file and options ...
// Initialize elements once the DOM is ready
$(this.updateDOM);
}
namespace.ScatterPlot.prototype = {
updateDOM: function() {
$("<canvas>")
.click(clickCallback)
.appendTo("#"+this.containerId);
//(...)
},
clickCallback: function() {
alert("Some click: "+this.id);
}
}
})();
每个对象都可以使用:
创建var v1 = new namespace.ScatterPlot("container1", "foo", "foo");
var v2 = new namespace.ScatterPlot("container2", "foo", "foo");
这里有两个问题:(1)在updateDOM中,'this'没有引用我的初始ScatterPlot对象,这意味着这个例子永远不会工作,而且(2)类似地,clickCallback将无法引用带有'this'的散点图。
我是javascript的新手,我仍然在用javascript来理解OO编程的逻辑,所以问题是:我在这里采取了错误的方向吗?经过一番挖掘,我可以通过将其传递给updateDOM来粗略地实现我想要的东西:
$(this.updateDOM(this)); // This blows my eyes but does the trick, at least partially
updateDOM: function(that) {
$("<canvas>")
.click(that.clickCallback)
.appendTo("#"+that.containerId);
//(...)
},
clickCallback: function() {
// Not working either... Should pass 'that' to the function too
alert("Some click: "+this.id);
}
但是我不认为这些图案非常优雅......而且关于点击回调问题也没有解决。
想法?
答案 0 :(得分:2)
查看MDN's introduction to the this
keyword。
处理该问题的标准方法是使用that
变量 - 不作为参数,而是使用单独的函数:
var that = this;
$(function() {
that.updateDOM();
});
// or
$(this.getClickCallback());
...
namespace.ScatterPlot.prototype.getClickCallback = function() {
var that = this;
return function clickCallback(e) {
alert("Some click: "+that.id);
};
};
或者,您可以随时使用.bind()
(或$.proxy
用于较旧的浏览器),这与第二个示例的做法完全相同:
$(this.clickCallback.bind(this));