проблема 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(); }); }