Javascript 无法读取属性';推动';重构代码时未定义的
我想让这段代码更简单:Javascript 无法读取属性';推动';重构代码时未定义的,javascript,d3.js,Javascript,D3.js,我想让这段代码更简单: links.forEach(function(link) { link.source = nodes[link.source] || (nodes[link.source] = { name: link.source }); link.target = nodes[link.target] || (nodes[link.target] = { name: lin
links.forEach(function(link) {
link.source = nodes[link.source] ||
(nodes[link.source] = {
name: link.source
});
link.target = nodes[link.target] ||
(nodes[link.target] = {
name: link.target
});
console.log(nodes)
});
因此,我对其进行了如下重构:
links.forEach(function(link) {
if (nodes[link.source] == null) {
nodes[link.source] = {
name: link.source
};
} else if (nodes[link.target] == null) {
nodes[link.target] = {
name: link.target
};
} else {
console.log('Not problem');
}
});
但是,现在我得到了这个错误:
无法读取未定义的属性“push”
这是完整的原始代码:
<DOCTYPE html>
<meta charset="utf-8">
<style>
.node {
fill: #4D00DD;
stroke: #fff;
stroke-width: 2px;
}
.link {
stroke: #777;
stroke-width: 8px;
}
</style>
<body>
<script src="https://d3js.org/d3.v3.min.js"></script>
<script>
var width = 1080,
height = 960;
var links = [
{ source : "Baratheon", target : "Lannister"},
{ source : "Baratheon", target : "Stark"},
{ source : "Lannister", target : "Stark"},
];
var nodes = {};
// parse links to nodes
links.forEach(function(link) {
link.source = nodes[link.source] ||
(nodes[link.source] = {name: link.source});
link.target = nodes[link.target] ||
(nodes[link.target] = {name: link.target});
console.log(nodes)
});
// add svg to our body
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var force = d3.layout.force()
.size([width, height])
.nodes(d3.values(nodes))
.links(links)
.on("tick", tick)
.linkDistance(600)
.start();
var link = svg.selectAll(".link")
.data(links)
.enter().append("line")
.attr("class", "link")
var node = svg.selectAll(".node")
.data(force.nodes())
.enter().append("circle")
.attr("class", "node")
.attr("r", width * 0.03);
function tick(e) {
node.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
.call(force.drag);
link.attr("x1", function(d) { return d.source.x; })
.attr('y1', function(d) { return d.source.y; })
.attr('x2', function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; })
}
</script>
.节点{
填充:4D00DD;
冲程:#fff;
笔画宽度:2px;
}
.链接{
行程:777;
笔划宽度:8px;
}
可变宽度=1080,
高度=960;
变量链接=[
{来源:“Baratheon”,目标:“Lannister”},
{来源:“Baratheon”,目标:“Stark”},
{来源:“兰尼斯特”,目标:“斯塔克”},
];
var节点={};
//解析到节点的链接
links.forEach(函数(link){
link.source=节点[link.source]||
(节点[link.source]={name:link.source});
link.target=节点[link.target]||
(节点[link.target]={name:link.target});
console.log(节点)
});
//将svg添加到我们的身体中
var svg=d3.选择(“正文”).追加(“svg”)
.attr(“宽度”,宽度)
.attr(“高度”,高度);
var-force=d3.layout.force()
.尺寸([宽度、高度])
.节点(d3.值(节点))
.链接(links)
.on(“滴答”,滴答)
.linkDistance(600)
.start();
var link=svg.selectAll(“.link”)
.数据(链接)
.enter().append(“行”)
.attr(“类”、“链接”)
var node=svg.selectAll(“.node”)
.data(force.nodes())
.enter().append(“圆”)
.attr(“类”、“节点”)
.attr(“r”,宽度*0.03);
功能勾号(e){
attr(“cx”,函数(d){return d.x;})
.attr(“cy”,函数(d){返回d.y;})
.呼叫(强制拖动);
attr(“x1”,函数(d){返回d.source.x;})
.attr('y1',函数(d){返回d.source.y;})
.attr('x2',函数(d){返回d.target.x;})
.attr(“y2”,函数(d){返回d.target.y;})
}
您试图使该块更易于阅读,这是一个非常好的练习。但是,你忘了什么
在原始代码中,此任务
link.source = nodes[link.source] || (nodes[link.source] = {name: link.source});
。。。以非常详细的方式表示:
节点[link.source]
是否存在?如果是,则使link.source=节点[link.source]
。如果否,则使节点[link.source]={name:link.source}
,然后使link.source=节点[link.source]
但是在if
逻辑中,您从未设置link.source
if节点[link.source]
存在
此外,您不需要:
if (nodes[link.source] == null) {
一个简单的if(!nodes[link.source]){
将起作用
最后,删除else
。无论第一个if
的结果如何,都必须对第二个if
进行评估
综上所述,这应该是您的重构代码:
links.forEach(function(link) {
if (!nodes[link.source]) {
nodes[link.source] = {
name: link.source
}
};
//Look, Ma, no 'else' here!
if (!nodes[link.target]) {
nodes[link.target] = {
name: link.target
}
};
//add these lines:
link.source = nodes[link.source];
link.target = nodes[link.target];
});
下面是正在运行的演示:
var宽度=600,
高度=300;
变量链接=[{
资料来源:“Baratheon”,
目标:“兰尼斯特”
}, {
资料来源:“Baratheon”,
目标:“斯塔克”
}, {
资料来源:“兰尼斯特”,
目标:“斯塔克”
},
];
var节点={};
links.forEach(函数(link){
如果(!节点[link.source]){
节点[link.source]={
名称:link.source
}
};
如果(!节点[link.target]){
节点[link.target]={
名称:link.target
}
};
link.source=节点[link.source];
link.target=节点[link.target];
});
//将svg添加到我们的身体中
var svg=d3.选择(“正文”).追加(“svg”)
.attr(“宽度”,宽度)
.attr(“高度”,高度);
var-force=d3.layout.force()
.尺寸([宽度、高度])
.节点(d3.值(节点))
.链接(links)
.on(“滴答”,滴答)
.linkDistance(50)
.start();
var link=svg.selectAll(“.link”)
.数据(链接)
.enter().append(“行”)
.attr(“类”、“链接”)
var node=svg.selectAll(“.node”)
.data(force.nodes())
.enter().append(“圆”)
.attr(“类”、“节点”)
.attr(“r”,宽度*0.03);
功能勾号(e){
node.attr(“cx”,函数(d){
返回d.x;
})
.attr(“cy”,函数(d){
返回d.y;
})
.呼叫(强制拖动);
link.attr(“x1”,函数(d){
返回d.source.x;
})
.attr('y1',函数(d){
返回d.source.y;
})
.attr('x2',函数(d){
返回d.target.x;
})
.attr(“y2”,功能(d){
返回d.target.y;
})
}
在您的代码示例中没有推送
。欢迎使用堆栈溢出。我对您的问题做了很多更改,请仔细查看,注意我更改了什么以及为什么更改。另外,请领导。非常感谢您的友好回答,但我有一个问题,我认为“link.source”、“link.target”毫无意义。Bec因为“link.source”已经有了“Baratheon”或“Lannister”这样的值。那么,为什么要有“link.source”、“link.target”呢分配行是必需的?我不知道这些行在哪里使用。它们不同:links
是数组。link
,它只是forEach
函数的一个参数,是对象,它可以有任何其他名称。请检查我的另一个答案,不要评论。我需要你的帮助。我很抱歉我的巨大错误柯。@specialscene不用担心。谢谢你把它作为一个新问题发布。