命名空间的javascript问题,“this”和库

时间:2014-02-11 14:19:45

标签: javascript namespaces scope queue javascript-namespaces

我正在构建一个可视化页面(带有dc.js),我决定跳转并将其全部收集到一个命名空间中。来自Python的简单性,碰到JavaScript的范围疯狂已经足够强大,所以请耐心等待。

我有一个通用的JS结构如下:

var NamespaceClass = function() {

    this.var0 = "something";
    this.var1 = dc.SomeChartClass("#some-css-selector");

    this.setup = function(error, config, dataset) {
        console.log("Inside setup:", this);
        this.var2 = this.process_data(dataset);
        // Do some more stuff...
    }

    this.process_data = function(data) {
        var whatever;
        //Do stuff with "data"...
        return whatever;
    }

    this.start = function() {
        console.log("Inside start:", this);
        var q;

        q = queue().defer(d3.json, "config.json")
                   .defer(d3.csv, "data.csv");
        q.await(this.setup);
    }
}

var MyNamespace = new NamespaceClass();
MyNamespace.start();

其中queueMike Bostock's queue lib,用于异步文件排队。当我尝试测试脚本时,我进入控制台:

Inside start: Object { var0 = "something", var1={...}, more...}
Inside setup: Window testpage.html
TypeError: this.process_data is not a function

因此,从setup调用q.await会使对象的范围(或者在JavaScript中调用的任何内容)松散。我怎么能避免这个?我也尝试使用代理对象,如:

    this.start = function() {
        console.log("Inside start:", this);
        var q, proxy;

        q = queue().defer(d3.json, "config.json")
                   .defer(d3.csv, "data.csv");
        proxy = this.setup;
        q.await(proxy);
    }

无济于事!

1 个答案:

答案 0 :(得分:2)

this的值取决于您如何调用包含它的函数。您无法控制setup函数的调用方式,因为它是在q.await函数内调用的。

执行q.await(this.setup)时,会传递对函数设置的引用,但“丢失”与命名空间的任何连接。您需要将函数绑定到命名空间,以使其具有正确的this值:

q.await(this.setup.bind(this));

更好的是,因为只有this是命名空间时你的所有函数才有效,所以你应该将它们绑定到命名空间,如下所示:

this.start = function() {
  // body
}.bind(this);

// usage:
q.await(this.setup);

现在无论你传递给他们什么,他们都会有正确的this

注意:在这种情况下,bind的工作原理如下:

this.start = function() {
    var namespace = this;

    q.await(function(){ namespace.setup(); });
}
相关问题