D3-Force中nodes自动生成力模拟属性的JS执行顺序疑问
问题解答:d3.map处理后节点自动出现forceSimulation属性的原因
首先明确:d3.map本身不会给节点对象添加index、x、y、vx、vy这些属性,这些属性是d3.forceSimulation初始化时自动注入到节点对象中的。你看到的现象核心原因是Observable的响应式执行机制,而非JavaScript的线性执行顺序。
具体机制拆解:
Observable的响应式单元格
Observable中的代码单元格基于依赖关系自动执行。如果创建力导向模拟的simulation单元格依赖nodes单元格,那么只要nodes的值发生变化,simulation就会自动重新运行。两次日志的实际执行场景
- 第一次
console.log(nodes):输出的是上一次运行后,已经被simulation处理过的节点数组(此时节点已带有模拟所需的属性)。 - 执行
nodes = d3.map(nodes, (_, i) => ({id: N[i]})):创建了仅包含id属性的新对象数组。但因为simulation依赖nodes,Observable会立即触发simulation重新运行——d3.forceSimulation(nodes)会遍历新数组中的每个对象,自动添加index、x、y、vx、vy这些模拟所需的内部属性。 - 第二次
console.log(nodes):此时输出的是已经被simulation处理过的新节点数组,因此能看到那些属性。
- 第一次
验证方法
暂时注释掉创建simulation的代码单元格,重新运行后会发现:d3.map处理后的节点数组仅包含id属性,不会出现index、x等模拟相关属性,以此证明这些属性确实是d3.forceSimulation添加的。
内容的提问来源于stack exchange,提问作者MMLi
相关产品推荐
相关产品推荐

