在 javascript 对象中搜索具有特定值的属性?
我有一个 javascript 对象,我想
递归
搜索它以查找包含特定值的任何属性。
我正在使用的 javascript 已被最小化,并且不太容易追踪。
背景
我正在使用 Bing Maps AJAX SDK。它能够添加其他图块层。每个图块层都有一个图块源对象,它指定图块 URL 的 URI 格式。
我遇到了一个问题,即图块源 URI 只创建一次,然后被缓存。因此我无法针对每个请求动态更改 URL 的参数(例如,根据一天中的时间更改图块叠加层的颜色)。
请注意,此行为与 Google 的 Map API 和适用于 WP7 的 Bing Maps API 不同,这两个 API 都允许您为每个图块请求动态创建 URL。
查找缓存的 URI,替换两个特定参数,然后使用 URI 来获取图块。
由于这是 javascript,我想找到缓存的 URI,并用一个函数替换它,该函数动态构建 URI 并返回它。
我不需要每次运行时都这样做,只是想知道属性被缓存在哪里,所以我可以编写代码来对其进行 hax0r。
原始问题
如果我将 URI 设置为某个值(如“floobieblaster”),当我设置断点时,我可以递归搜索 javascript 对象以查找“floobieblaster”并获取存储该值的属性吗?
编辑以添加
我正在搜索的对象似乎有一个循环引用,因此任何递归代码都可能导致 stackoverflow。
有什么编辑器/调试器技巧可以利用吗?
类似这样的简单操作应该可以工作:
var testObj = {
test: 'testValue',
test1: 'testValue1',
test2: {
test2a: 'testValue',
test2b: 'testValue1'
}
}
function searchObj (obj, query) {
for (var key in obj) {
var value = obj[key];
if (typeof value === 'object') {
searchObj(value, query);
}
if (value === query) {
console.log('property=' + key + ' value=' + value);
}
}
}
如果您执行
searchObj(testObj, 'testValue');
,它将在控制台中记录以下内容:
property=test value=testValue
property=test2a value=testValue
显然,您可以用任何您想要的内容替换
console.log
,或者向
searchObj
函数添加回调参数以使其更具可重用性。
编辑:
添加了
query
参数,该参数允许您在调用该函数时指定要搜索的值。
此函数将在对象中搜索。它将搜索查询与对象的每个属性进行匹配。当您需要在多维对象中搜索时,这很有用 经过几个小时的努力,我从 Google 的 AngularJS 项目获得了此代码。
/* Seach in Object */
var comparator = function(obj, text) {
if (obj && text && typeof obj === 'object' && typeof text === 'object') {
for (var objKey in obj) {
if (objKey.charAt(0) !== '$' && hasOwnProperty.call(obj, objKey) &&
comparator(obj[objKey], text[objKey])) {
return true;
}
}
return false;
}
text = ('' + text).toLowerCase();
return ('' + obj).toLowerCase().indexOf(text) > -1;
};
var search = function(obj, text) {
if (typeof text == 'string' && text.charAt(0) === '!') {
return !search(obj, text.substr(1));
}
switch (typeof obj) {
case "boolean":
case "number":
case "string":
return comparator(obj, text);
case "object":
switch (typeof text) {
case "object":
return comparator(obj, text);
default:
for (var objKey in obj) {
if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {
return true;
}
}
break;
}
return false;
case "array":
for (var i = 0; i < obj.length; i++) {
if (search(obj[i], text)) {
return true;
}
}
return false;
default:
return false;
}
};
以下是针对这个老问题的一些现代解决方案。您可以扩展它以满足自己的需求。假设数据结构如下:
table = {
row1: {
col1: 'A',
col2: 'B',
col3: 'C'
},
row2: {
col1: 'D',
col2: 'A',
col3: 'F'
},
row3: {
col1: 'E',
col2: 'G',
col3: 'C'
}
};
获取属性
col3
等于“C”的对象的键数组:
Object.keys(table).filter(function(row) {
return table[row].col3==='C';
});
这将返回
['row1', 'row3']
。
获取属性
col3
等于“C”的行的新对象:
Object.keys(table).reduce(function(accumulator, currentValue) {
if (table[currentValue].col3==='C') accumulator[currentValue] = table[currentValue];
return accumulator;
}, {});
这将返回
{
row1: {
col1: 'A',
col2: 'B',
col3: 'C'
},
row3: {
col1: 'E',
col2: 'G',
col3: 'C'
}
}
请注意,以上答案来自 类似问题 。