使用jQuery引用回调函数中的父对象

时间:2012-11-20 13:49:19

标签: javascript jquery

我有一个动态生成的页面,其中包含一定数量(用户动态定义)的高级散点图。我打算创建一个定义散点图本身的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);
}

但是我不认为这些图案非常优雅......而且关于点击回调问题也没有解决。

想法?

1 个答案:

答案 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));