在javascript对象中搜索具有特定值的属性?

在javascript对象中搜索具有特定值的属性?,javascript,Javascript,我有一个javascript对象,我想递归地搜索它,以找到包含特定值的任何属性 我正在使用的javascript已经被缩小,并且不太容易跟踪 背景 我正在使用Bing地图AJAX SDK。它能够添加额外的平铺层。每个tilelayer都有一个tilesource对象,用于指定tile URL的URI格式 我遇到了一个问题,TileSourceURI只创建一次,然后缓存。因此,我无法为每个请求动态更改URL的参数(例如,根据一天中的时间更改平铺覆盖的颜色) 请注意,这种行为与Google的Map

我有一个javascript对象,我想递归地搜索它,以找到包含特定值的任何属性

我正在使用的javascript已经被缩小,并且不太容易跟踪

背景

我正在使用Bing地图AJAX SDK。它能够添加额外的平铺层。每个tilelayer都有一个tilesource对象,用于指定tile URL的URI格式

我遇到了一个问题,TileSourceURI只创建一次,然后缓存。因此,我无法为每个请求动态更改URL的参数(例如,根据一天中的时间更改平铺覆盖的颜色)

请注意,这种行为与Google的Map API和用于WP7的Bing Maps API不同,后者都允许您为每个磁贴请求动态创建URL

查找缓存的URI,并替换两个特定参数,然后使用URI获取磁贴

由于这是javascript,我希望找到缓存的URI,并用一个函数替换它,该函数将动态构建URI并返回它

我不需要在每次运行时都这样做,只想知道属性缓存在哪里,这样我就可以为它编写代码

原始问题

如果我将URI设置为“floobieblaster”之类的值,当我设置断点时,我可以递归地搜索javascript对象以查找“floobieblaster”并获取存储该值的属性吗

编辑以添加

我正在搜索的对象似乎有一个循环引用,因此任何递归代码都可能导致堆栈溢出


有什么编辑器/调试器技巧我可以使用吗?

像这样简单的东西应该可以使用:

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
参数,该参数允许您指定调用函数时要搜索的值。

这是我的解决方案,它使用正则表达式测试匹配给定的字符串/值,并返回匹配的数组。它不是递归的,但是您已经从问题中删除了它

这是我在以下线程中的回答:

同样的原则,正如其他人所建议的——搜索对象以获得给定的值,搜索此解决方案的任何人

职能:

Array.prototype.findValue = function(name, value){
   var array = $.map(this, function(v,i){
        var haystack = v[name];
        var needle = new RegExp(value);
        // check for string in haystack
        // return the matched item if true, or null otherwise
      return needle.test(haystack) ? v : null;
   });
  return this;
}
你的目标:

myObject = {
        name : "soccer",
        elems : [
            {name : "FC Barcelona"},
            {name : "Liverpool FC"}
        ]
    },
    {
        name : "basketball",
        elems : [
            {name : "Dallas Mavericks"}
        ]
    }
使用方法:

(这将在myObject.elems数组中搜索与“FC”匹配的“name”)

结果-检查您的控制台:

[Object, Object, keepMatching: function, findValue: function]
0: Object
name: "FC Barcelona"
__proto__: Object
1: Object
name: "Liverpool FC"
__proto__: Object
length: 2
__proto__: Array[0]
如果想要精确匹配,只需将三元语句中的正则表达式更改为基本值匹配即可。 i、 e


此函数将在对象中搜索。它将搜索查询与对象的每个属性相匹配。当您需要在多维对象中搜索时,这非常有用 花了几个小时后,我从谷歌的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;
}
};
/*搜索对象*/
var比较器=功能(obj,文本){
如果(obj&&text&&typeof obj=='object'&&typeof text=='object'){
for(obj中的变量objKey){
if(objKey.charAt(0)!='$'&&hasOwnProperty.call(obj,objKey)&&
比较器(obj[objKey],text[objKey])){
返回true;
}
}
返回false;
}
text=(''+text).toLowerCase();
返回(“”+obj).toLowerCase().indexOf(text)>-1;
};
变量搜索=功能(对象,文本){
如果(文本类型=='string'&&text.charAt(0)=='!'){
return!search(obj,text.substr(1));
}
开关(obj类型){
案例“布尔”:
案例“编号”:
大小写“字符串”:
返回比较器(obj,文本);
案例“对象”:
开关(文本类型){
案例“对象”:
返回比较器(obj,文本);
违约:
for(obj中的变量objKey){
if(objKey.charAt(0)!='$'&&search(obj[objKey],text)){
返回true;
}
}
打破
}
返回false;
案例“数组”:
对于(变量i=0;i
基于Bryan的方法,这里有一个更方便的现成静态方法:

/**
* Find properties matching the value down the object tree-structure.
* Ignores prototype structure and escapes endless cyclic nesting of
* objects in one another.
*
* @param {Object} object Object possibly containing the value.
* @param {String} value Value to search for.
* @returns {Array<String>} Property paths where the value is found. 
*/
getPropertyByValue: function (object, value) {
  var valuePaths;
  var visitedObjects = [];

  function collectValuePaths(object, value, path, matchings) {

    for (var property in object) {

      if (
        visitedObjects.indexOf(object) < 0 &&
        typeof object[property] === 'object') {

        // Down one level:

        visitedObjects.push(
          object);

        path =
          path +
          property + ".";

        collectValuePaths(
          object[property],
          value,
          path,
          matchings);
      }

      if (object[property] === value) {

        // Matching found:

        matchings.push(
          path +
          property);
      }

      path = "";
    }

    return matchings;
  }

  valuePaths =
    collectValuePaths(
      object,
      value,
      "",
      []);

   return valuePaths;
}
将导致

["test", "test2.test2a"]

我编辑了Bryan Downing answer以打印深层对象的层次结构:

   function searchObj (obj, query, prefix /*not to be set*/) {
    prefix = prefix || "---";
    var printKey;

    for (var key in obj) {
        var value = obj[key];

        if (typeof value === 'object') {
            if (searchObj(value, query, prefix + "|---")) {
                console.log(prefix + ' ' + key);
                printKey = true;
            }
        }

        if (value === query) {
            console.log(prefix + ' ' + key + ' = ' + value);

            return true;
        }
    }

    return printKey;
}

然后,运行
searchObj(testObj,'testValue')

这里有一些解决这个老问题的现代方法。您可以扩展它以满足您自己的需要。假设以下数据结构:

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';
});
Object.keys(table).reduce(function(accumulator, currentValue) {
  if (table[currentValue].col3==='C') accumulator[currentValue] = table[currentValue];
  return accumulator;
}, {});
这将返回
['row1','row3']

获取属性
col3
等于“C”的行的新对象:

Object.keys(table).filter(function(row) {
  return table[row].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'
  }
}

请注意,上面的答案来自。

我认为我可以将对象转储到json中,并以这种方式进行搜索。也许有更好的办法?--没有。看起来该对象具有循环结构。Crockford的库(参见cycle.js)支持将循环对象编码和解码为json(+jsonpath)。您可以按照您的建议进行序列化和搜索,或者只需稍微更改代码即可直接实现您的目标。+1但为了防止在
[[Prototype]]
链上搜索对象,应包括
hasOwnProperty
测试。考虑<代码> > ObjyType Obj[Ky]=''函数'/COD> >的测试。这显然处理递归结构,可接受的答案不适用。当我使用Chrome DEV工具时,我得到最大堆栈超过的错误。
{
  row1: {
    col1: 'A',
    col2: 'B',
    col3: 'C'
  },
  row3: {
    col1: 'E',
    col2: 'G',
    col3: 'C'
  }
}