我正在构建一个可视化页面(带有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();
其中queue
为Mike 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);
}
无济于事!
答案 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(); });
}