我正在尝试创建一个函数,这样你就可以遍历一个包含很多对象的大对象,并按值找到一个特定的方法。我想通过使用break语句在找到值时停止函数中的循环。这是我的代码。
let fake_window = {
aaa: "aaa",
bbb: "bbb",
ccc: "ccc",
ddd: function ddd() {
console.log('ddd');
},
eee: {
eea: "eea",
eeb: "eeb",
eec: "eec"
},
fff: {
ffa: "ffa",
ffb: "ffb",
ffc: {
fac: "fac",
fbc: "fbc",
fcc: "fcc",
fdc: "fdc"
}
},
ggg: {
gga: {
gaa: "gaa",
gba: "gba"
},
ggb: "ggb"
}
};
const window_loop = function (window_obj, value) {
for (const prop in window_obj) {
if (window_obj.hasOwnProperty(prop)) {
if (value) {
if (value === window_obj[prop]) { // when value is found
console.log("FOUND, NOW STOP!");
break;
}
}
console.log(prop + ' => ' + window_obj[prop]);
if (typeof window_obj[prop] === "object") {
window_loop(window_obj[prop], value);
}
}
}
};
window_loop(fake_window, 'fbc');
当找到值时,我控制台“找到了,现在停止!”然后我打破了循环。但由于某种原因,循环不断迭代。有人可以帮我解释为什么会这样吗?
答案 0 :(得分:1)
您的问题是,在递归调用fbc
并且window_loop
的返回值未用于打破外部循环时,达到window_loop
值。
您可以对window_loop
方法进行一些更改(评论内嵌)
window_loop = function (window_obj, value) {
var isFound = false; //new flag is introduced
for (const prop in window_obj) {
if (window_obj.hasOwnProperty(prop)) {
if (value) {
if (value === window_obj[prop]) { // when value is found
console.log("FOUND, NOW STOP!");
isFound = true;
break;
}
}
console.log(prop + ' => ' + window_obj[prop]);
if (typeof window_obj[prop] === "object") {
isFound = window_loop(window_obj[prop], value);
if ( isFound ) //break when returned value from loop is true
{
break;
}
}
}
}
return isFound; //return this value
};
另一种简洁的方法是
var window_loop = function (window_obj, value) {
//return the value of find
return Object.keys( window_obj ).find( function( key ){
if (typeof window_obj[key] === "object") {
//invoke window_loop recursively if the value is object.
return window_loop(window_obj[key], value);
}
if ( value == key )
{
console.log("FOUND, NOW STOP!", key);
}
else
{
console.log("Not FOUND, continue !", key);
}
return value == key;
})
};
<强>演示强>
var fake_window = {
aaa: "aaa",
bbb: "bbb",
ccc: "ccc",
ddd: function ddd() {
console.log('ddd');
},
eee: {
eea: "eea",
eeb: "eeb",
eec: "eec"
},
fff: {
ffa: "ffa",
ffb: "ffb",
ffc: {
fac: "fac",
fbc: "fbc",
fcc: "fcc",
fdc: "fdc"
}
},
ggg: {
gga: {
gaa: "gaa",
gba: "gba"
},
ggb: "ggb"
}
};
var window_loop = function (window_obj, value) {
return Object.keys( window_obj ).find( function( key ){
if (typeof window_obj[key] === "object") {
return window_loop(window_obj[key], value);
}
if ( value == key )
{
console.log("FOUND, NOW STOP!", key);
}
else
{
console.log("Not FOUND, continue !", key);
}
return value == key;
})
};
window_loop(fake_window, 'fbc');
&#13;
答案 1 :(得分:1)
请考虑以下代码段:
var pre = document.getElementById("trace");
f(0, "root", {
a: { aa: "aa", ab: "ab", ac: "ac" },
b: { ba: "ba", bb: "bb", bc: "bc" }
});
function f(depth, name, tree) {
log(depth, "call f on \"" + name + "\"");
log(depth + 1, "for each child of \"" + name + "\"");
for (let name in tree) {
log(depth + 2, "child \"" + name + "\"");
if (!isLeaf(tree[name])) {
log(depth + 2, "if child is not a leaf");
f(depth + 3, name, tree[name]);
} else if (name === "aa") {
log(depth + 2, "if child is \"aa\"");
log(depth + 3, color("red", "break"));
break;
}
}
}
function isLeaf(node) {
return node.hasOwnProperty("length");
}
function color(c, s) {
return "<span style=\"color:" + c + "\">" + s + "</span>";
}
function log(depth, line) {
for (let i = 0; i < depth; i++) {
if ((i + 2) % 3 === 0) {
pre.innerHTML += color("red", "| ");
} else if ((i + 1) % 3 === 0) {
pre.innerHTML += color("gray", "| ");
} else {
pre.innerHTML += color("blue", "| ");
}
}
pre.innerHTML += line + "\n";
}
pre{font-family:Consolas,Menlo,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New,monospace,sans-serif;font-size:12px;display:inline-block;vertical-align:top;margin:0}
#trace{padding-left:12px;border-left:12px solid #ddd;margin-left:12px}
<pre>
function f(depth, name, tree) {
for (let name in tree) {
if (!isLeaf(tree[name])) {
f(depth + 3, name, tree[name]);
} else if (name === "aa") {
break;
}
}
}
f(0, "root", {
a: { aa: "aa", ab: "ab", ac: "ac" },
b: { ba: "ba", bb: "bb", bc: "bc" }
});
</pre><pre id="trace"></pre>
输出的右侧部分是执行的痕迹。以下是阅读方法:
for
循环范围。您需要知道的是break
语句对最接近的红线的左侧没有影响,在技术上,它在for
循环范围之外没有任何影响。根据这些信息,您应该能够弄清楚自己发生了什么。
我希望你不要责怪我尝试原创方法: - )