0

我有一个动态生成的页面,其中包括一定数量(用户动态定义)的高级散点图。我打算创建一个定义散点图本身的 JavaScript 对象,即它采用一些参数、一些数据和一些容器 ID,并将创建获得可视化所需的各种元素:画布元素、工具栏等。这样做,我从以下(简化的)类开始:

(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 将无法引用散点图'这' 要么。

我是 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);
}

但我不觉得这种模式很优雅......关于点击回调的问题也没有解决。

想法?

4

1 回答 1

2

看看MDN 对this关键字的介绍。

处理该问题的标准方法是使用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));
于 2012-11-20T13:59:08.147 回答