проблема javascript с пространством имен, " это " и библиотекой
Я создаю страницу визуализации (с помощью dc.js), для которой я решил сделать прыжок и собрать все это в единое пространство имен. Исходя из простоты Python, столкновение с безумием scope 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 - это lib очереди Майка Бостока для асинхронной очереди файлов. Когда я пытаюсь протестировать скрипт, я получаю в консоли:
Inside start: Object { var0 = "something", var1={...}, more...}
Inside setup: Window testpage.html
TypeError: this.process_data is not a function
Итак, призывая setup from 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 ответ:
Значение
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(); }); }