假设我想在'StackOverflow'
中的所有声明变量中搜索值window
。
我可以用这段代码来完成:
function globalSearch(obj, value) {
for(var p in obj)
if(obj[p] == value)
return(p);
}
globalSearch(window, 'StackOverflow');
此代码将返回具有此值的变量的名称(或不返回任何内容)。
因此,如果我声明了一个值为'StackOverflow'
的变量,它将成功找到它。
我的问题是我想更深入地搜索window
的对象(及其自己的嵌套对象),以达到如下结果:
var x = 'StackOverflow' // returns 'x'
var y = { a : 'StackOverflow' } // returns 'y.a'
var z = { a : { b: 'StackOverflow' } } // returns 'z.a.b'
我遇到了Object的继承方法问题。有没有办法做到这一点?
答案 0 :(得分:15)
深度搜索但没有递归函数调用
功能递归具有内部堆栈限制并浪费内存。
添加了其他功能
搜索数组形式的递归对象保护;当然,它不会占用太多内存,因为对象仅存储为引用。
如果对象本身与值匹配,则返回true。否则它将返回''匹配为false。
数组使用角括号表示法。
代码
function globalSearch(startObject, value) {
var stack = [[startObject,'']];
var searched = [];
var found = false;
var isArray = function(test) {
return Object.prototype.toString.call( test ) === '[object Array]';
}
while(stack.length) {
var fromStack = stack.pop();
var obj = fromStack[0];
var address = fromStack[1];
if( typeof obj == typeof value && obj == value) {
var found = address;
break;
}else if(typeof obj == "object" && searched.indexOf(obj) == -1){
if ( isArray(obj) ) {
var prefix = '[';
var postfix = ']';
}else {
var prefix = '.';
var postfix = '';
}
for( i in obj ) {
stack.push( [ obj[i], address + prefix + i + postfix ] );
}
searched.push(obj);
}
}
return found == '' ? true : found;
}
<强>问题强>
如果不将初始变量名称传递给函数,我们就无法从头开始返回完全限定的变量名称。我想不出解决方案,如果有的话,我会感到惊讶。
带空格的变量名作为对象的键是有效的,其他无效变量名也是如此,它只是意味着必须使用尖括号来处理该值。我能想到几个解决方案。正则表达式检查每个变量名称以确保它是有效的,如果不是,则使用尖括号表示法。最重要的问题是reg-ex是一个页面长。或者,我们只能使用尖括号,但这对于OP原始问题并非如此。
对''搜索'数组的indexOf调用对于非常大的对象可能有点沉重,但我还不能想到另一种选择。
<强>改进强>
除了清理代码之外,如果函数返回一个匹配数组也会很好。这也引发了另一个问题,即返回的数组不包含对递归对象的引用。也许该函数可以接受结果格式配置参数。
答案 1 :(得分:5)
这应该有效。它使用递归来实现结果。
function globalSearch(obj, value) {
for(var p in obj)
if(obj[p] == value){
return(p);
}else if(typeof obj[p] == "object" && obj[p] != obj){
var te = globalSearch(obj[p], value);
if(te!=false){ return p + "." + te }
}
return false;
}
答案 2 :(得分:0)
使您的解决方案递归。如果您有对象,请再次调用您的函数。
function globalSearch(obj, value) {
for(var p in obj) {
if (obj[p] == value) {
return(p);
} else if (typeof obj[p] === "object") {
var recursiveCheck= globalSearch(obj[p], value);
if (recursiveCheck) {
return p + "." + recursiveCheck;
}
}
}
}
globalSearch(window, 'StackOverflow');
我敢打赌,大多数浏览器会因过多循环而发出警告。
答案 3 :(得分:0)
此代码基于另一个答案,允许找到所有可能的值匹配。
function globalSearch(startObject, value, returnFirstResult = false) {
var stack = [[startObject,'']];
var searched = [];
var found = new Set();
var isArray = function(test) {
return Object.prototype.toString.call( test ) === '[object Array]';
}
while(stack.length) {
var fromStack = stack.pop();
var obj = fromStack[0];
var address = fromStack[1];
if( typeof obj == typeof value && obj == value) {
if (returnFirstResult) {
return address == '' ? false : address;
}
found.add(address)
}if(typeof obj == "object" && searched.indexOf(obj) == -1){
if ( isArray(obj) ) {
var prefix = '[';
var postfix = ']';
}else {
var prefix = '.';
var postfix = '';
}
for( i in obj ) {
stack.push( [ obj[i], address + prefix + i + postfix ] );
}
searched.push(obj);
}
}
return Array.from(found);
}