我试图理解下面的代码中所发生的事情:
var dataset = [
{source: "Microsoft", target: "Amazon", type: "licensing"},
{source: "Microsoft", target: "HTC", type: "licensing"},
{source: "Samsung", target: "Apple", type: "suit"},
{source: "Motorola", target: "Apple", type: "suit"},
{source: "Nokia", target: "Apple", type: "resolved"},
{source: "HTC", target: "Apple", type: "suit"},
{source: "Kodak", target: "Apple", type: "suit"},
{source: "Microsoft", target: "Barnes & Noble", type: "suit"},
{source: "Microsoft", target: "Foxconn", type: "suit"},
{source: "Oracle", target: "Google", type: "suit"},
{source: "Apple", target: "HTC", type: "suit"},
{source: "Microsoft", target: "Inventec", type: "suit"},
{source: "Samsung", target: "Kodak", type: "resolved"},
{source: "LG", target: "Kodak", type: "resolved"},
{source: "RIM", target: "Kodak", type: "suit"},
{source: "Sony", target: "LG", type: "suit"},
{source: "Kodak", target: "LG", type: "resolved"},
{source: "Apple", target: "Nokia", type: "resolved"},
{source: "Qualcomm", target: "Nokia", type: "resolved"},
{source: "Apple", target: "Motorola", type: "suit"},
{source: "Microsoft", target: "Motorola", type: "suit"},
{source: "Motorola", target: "Microsoft", type: "suit"},
{source: "Huawei", target: "ZTE", type: "suit"},
{source: "Ericsson", target: "ZTE", type: "suit"},
{source: "Kodak", target: "Samsung", type: "resolved"},
{source: "Apple", target: "Samsung", type: "suit"},
{source: "Kodak", target: "RIM", type: "suit"},
{source: "Nokia", target: "Qualcomm", type: "suit"}
];
var nodes = {};
update(dataset);
function update(links){
var i = 1;
links.forEach(function(link){
// Pre iteration checks
console.log(i);
console.log(link.source);
console.log(nodes[link.source]);
// Observations – initial dataset is being overwritten?
// Should the following be read as “if one evaluates to true, do both?”
link.source = nodes[link.source] || (nodes[link.source] = {name: link.source, linkCount:0}); // Initialize new nodes with zero links
link.source.linkCount++;
// Post iteration checks
console.log(link.source);
console.log(nodes[link.source]); // This is undefined if link.source is now an object. This is effectively saying console.log(nodes[object])
console.log(nodes[link.source.name]); // This now says console.log(nodes["Microsoft"]) (for ex)
i++;
});
}如果我在每次迭代中写下我认为正在发生的事情,我会看到以下内容:
"Microsoft" = nodes["Microsoft"]?假。nodes["Microsoft"] = { name: "Microsoft", linkCount: 0 }linkCount + 1 so nodes["Microsoft"] = { name: "Microsoft", linkCount: 1 }"Microsoft" = nodes["Microsoft?"]?是真的。linkCount + 1 so nodes["Microsoft"] = { name: "Microsoft", linkCount: 2 }"Samsung" = nodes["Samsung"]?假。nodes["Samsung"] = { name: "Samsung", linkCount: 0 }linkCount + 1 so nodes["Samsung"] = { name: "Samsung", linkeCount: 1 }我怀疑我的困惑与OR (||)操作符的工作方式有关。我的想法是,如果LHS评估为错误,跳过它,做RHS。这样做不对吗?
编辑:
如果我只看第一次迭代;
dataset[0].source = nodes[dataset[0].source] || (nodes[dataset[0].source] = { name: dataset[0].source })我们希望双方都能实现。dataset.source应该设置为节点[dataset.source],我们希望为节点[dataset.source]设置“值”。
如果我试着像这样跑;
dataset[0].source = nodes[dataset[0].source];
nodes[dataset[0].source] = { name: dataset[0].source };然后,第一行运行良好,大概是将"Microsoft“替换为指向节点“微软”的指针,然后尝试用未定义的dataset.source值更新节点”microsoft“的名称,该值仅将节点”microsoft“的名称值设置为未定义。
如果我像这样尝试代码;
dataset[0].source = nodes[dataset[0].source] || nodes[dataset[0].source] = { name: dataset[0].source };然后,我得到了错误"Uncaught :无效的左方在赋值“-不确定为什么会这样?
最后如果我试着
dataset[0].source = nodes[dataset[0].source] || (nodes[dataset[0].source] = { name: dataset[0].source });在RHS周围加上括号,所有这些都可以正常工作。dataset.source是对象,节点[dataset.source]也是对象。
对于这三种不同的代码结构,这种行为发生的原因最终是我所不理解的,特别是为什么第三种代码能够工作。
发布于 2015-04-11 09:19:21
二元逻辑运算符 ||也被称为“默认”运算符。它通常不返回布尔值,而是返回第一个值,除非它是falsy,在这种情况下返回第二个值。换句话说,
a || b
字面上返回a或b。
例如,null || 4返回4。
是的,如果左侧为真,则完全忽略右侧表达式(解析但不求值)。
至于link.source,通过尝试为该字符串分配一个属性,代码将该字符串隐式装箱到一个对象中。字符串和数字都可以用这种方式装箱,既可以使用继承的方法和属性(例如,link.source.length来获取字符串的长度),也可以为它们分配新的方法和属性。它们通过这样做来保留它们的类型,这与如果您执行new String(link.source)时所发生的情况不同:这会创建一个在各个方面都类似于一个的真正对象。
发布于 2015-04-11 09:39:25
我不太清楚混淆在哪里,但代码是这样工作的:
var dataset = [ /*data*/]
var nodes = {}
update(dataset);正如预期的那样,这是将大量数据和节点初始化为空对象文本,然后调用update函数。
-
function update(links) {
var i = 1;
links.forEach(function(link)
{
//content
i++;
});
}这是对数组的迭代,增加了i的值。
这里有两个稍微切线的点--传递给foreach的回调不是自己递增,而是将索引作为其第二个参数;如果支持旧的浏览器,因为它不适用于前IE8浏览器,那么要小心使用forEach。
link.source = nodes[link.source] || (nodes[link.source] = {name: link.source, linkCount:0}); // initialize new nodes with zero links
link.source.linkCount++;这是循环code.The惰性"OR“操作符的关键所在--就像您提到的那样--如果左边是真实的,那么它就不会计算第一部分,所以
true || foo();永远不会评估"foo“函数。因此,如果nodeslink.source确实存在(并且是真实的,但定义的对象总是真实的),那么它将忽略第二部分,并将该值分配给link.source,覆盖现有的数据集。
如果左边的表达式是falsey,那么它将计算您的右侧,并在节点中创建节点并将其分配给link.source。
这意味着在代码运行结束时,节点将成为一个具有包含linkCounts和名称的属性的对象;数据集将是相同的数组,但是每个对象的源属性由相同的linkCount/name对象关联。
-
我不完全确定您希望您的代码如何工作,所以不确定这与您预期的运行有什么不同。
有一件事可能是问题,那就是您讨论比较link.source和nodeslink.source,但是在您编写的代码中没有出现这种情况,因为您使用的是赋值运算符,而不是双或三等号("==“或"===") --哪个是比较运算符?如果您想这样做,那么相关的行将是:
(link.source == nodes[link.source]) || (nodes[link.source] = {name: link.source, linkCount:0});我对在这种诡计中使用or操作符持谨慎态度,因为聪明的代码通常很难读懂,如果这就是您想要的,我倾向于使用标准if语句来提高可读性:
if(link.source !== nodes[link.source]) {
nodes[link.source] = {name: link.source, linkCount:0}
}然而,如果这是你想要的,那么它会给你一个奇怪而毫无意义的输出.=\
https://stackoverflow.com/questions/29576059
复制相似问题