Javascript 对象成员并在JS中访问它们

Javascript 对象成员并在JS中访问它们,javascript,Javascript,我对JavaScript非常陌生,正在尝试使用JS加载数据库,以基于数据库绘制一些散点图。我想加载两个数据库:一个数据库有我想绘制的信息,但也有每行的标识符,第二个数据库有一些关于基于ID的分组或分类的信息。其想法是使用第二个DB中的分类为散点图中的点着色。每个ID在第一个DB中可以有多行。以下是我加载数据库的方式: d3.csv('../data/db1.csv', function(data) { data.forEach(function(d) { d.x = +d

我对JavaScript非常陌生,正在尝试使用JS加载数据库,以基于数据库绘制一些散点图。我想加载两个数据库:一个数据库有我想绘制的信息,但也有每行的标识符,第二个数据库有一些关于基于ID的分组或分类的信息。其想法是使用第二个DB中的分类为散点图中的点着色。每个ID在第一个DB中可以有多行。以下是我加载数据库的方式:

d3.csv('../data/db1.csv', function(data) {
    data.forEach(function(d) {
        d.x = +d.x;
        d.y = +d.y;
        d.ID = d.ID;

        d3.csv('../data/db2.csv', function(p) {
            p.forEach(function(pp) {
                var group = pp.group;
                var id = pp.id;
                if(id === d.ID){
                    d.group = group;
                }
            });
        };

        console.log("d", d);
        console.log("d.group", d.group);
    });
});
现在问题出现在两行“console.log”上,第一行返回:

d Object { x: 0.0, y: 0.0, ID: "000", group: 0, ...}
d.group undefined
但第二行返回:

d Object { x: 0.0, y: 0.0, ID: "000", group: 0, ...}
d.group undefined
我不明白的是,为什么对象
d
具有
group
的正确值,但是
d.group
实际上没有定义。
d.group
不应该指向
d
组成员吗

更新:

基于下面的建议,我尝试了一些其他版本。第一:

d3.csv(...
    data.forEach(...
        ...
        d3.csv(...
            ...
            //do the post processing here
        });
     });

     data.forEach(function(d){
         console.log('d', d);
         console.log('d.something', d.something);
     });
});
以及:

d3.csv(...
    data.forEach(...
        ...
        d3.csv(...
            ...
        });
     });

     data.forEach(function(d){
         //do the post processing here
     });

     data.forEach(function(d){
         console.log('d', d);
         console.log('d.something', d.something);
     });
});
在这两个版本中,我都遇到了相同的问题,带有
console.log(d)
的行打印得很好,并且带有
d.something
,这应该是后期处理的结果。但是带有
console.log(d.something)
的行显示为
undefined


这不仅仅是
控制台.log
,我还尝试在FireFox的inspect元素中调试它,并添加了一些手表,同样的情况也在那里发生。

您所面临的问题是javascript的异步性以及它提供的运行到完成保证

长话短说,由于加载CSV文件是一个异步操作,javascript将在运行处理CSV文件的回调函数之前完全运行父函数。因此,您只能在组数据加载后访问它(只有在执行回调时才能保证)。因此,即使console.log函数是在组加载之后出现的,但它们在组数据加载之前执行

如果将console.log调用移动到最内部的函数中,它们都将工作


您可以阅读更多关于这方面的内容,

当db2.csv中没有匹配项时,第二行中的d.group将是未定义的,因为它从未达到if条件,并且d对象的日志将没有group属性。因此,在某些情况下,这是预期的行为。您确定只有在这些情况下才会看到未定义的吗?@stephen.vakil不幸的是,即使存在匹配项,也会显示未定义的。感谢您让我了解此异步性。在实际的页面中,我需要对数据进行一些后处理,而不是仅仅记录它们,然后在
data.forEach(…)之后
但是仍然在
d3.csv(,function(){})中我有一些代码使用dc.js进行散点绘制。到那时,
d
s的所有成员都应该被定义,对吗?因此,如果我添加另一个
data.forEach(…)
在第一个forEach之后,在第二个forEach()的回调函数中移动第二个
for
所需的任何后期处理,我应该可以,对吗?是的,如果它在第二个forEach之后,但是仍然在第二个.csv()的回调函数中,那么您应该可以。(即,
}之间)
}-原始代码中console.log语句前的两行非空行。很抱歉延迟回复,我无法在周末对此进行测试。根据你的建议,我确实尝试了几种不同的想法,但它们导致了相同的
未定义的
行为。最后,我用其他方法更新了我的问题。再次感谢。你的第一个更新版本是正确的一半,因为你在评论中做了后期处理。但这也是您应该放置
控制台的地方。记录
调用和任何其他依赖于已处理数据的内容,因为在实际处理数据之前,您无法访问已处理数据。尽管示例中的
console.log
语句看起来像是在数据处理之后出现的,但实际上并非如此,因为传递给第二个
.csv()
的函数只有在第一个
.csv()
回调完成后才能执行。这更多的是您必须习惯的异步编程(它也存在于C++中,但它有多线程,所以它的行为不同。在我看来,JavaScript的运行到完成保证是上天派来的,即使它使JS引擎真正并行化)。我建议您读一下承诺,它们使异步更加明智,看起来更同步。