2012-02-23 54 views
14

Tôi có đối tượng javascript và tôi muốn đệ quy tìm kiếm nó để tìm bất kỳ thuộc tính nào chứa giá trị cụ thể.Tìm đối tượng javascript cho thuộc tính có giá trị cụ thể?

javascript tôi đang làm việc với đã được rút gọn và không dễ dàng theo dõi.

nền

Tôi đang sử dụng Bing Maps AJAX SDK. Nó có khả năng thêm các lớp gạch bổ sung. Mỗi tilelayer có một đối tượng brickource, chỉ định định dạng URI cho URL của tile.

Tôi đã gặp sự cố trong đó URI tileource được tạo một lần và được lưu trong bộ nhớ cache. Do đó, tôi không thể thay đổi động các thông số của URL (ví dụ: để thay đổi màu của lớp phủ ngói dựa trên thời gian trong ngày) cho mỗi yêu cầu. Lưu ý rằng hành vi này khác với API bản đồ của Google và API Bản đồ Bing cho WP7, cả hai đều cho phép bạn tạo động URL cho mỗi yêu cầu lát.

URI được lưu trong bộ nhớ cache được tra cứu và hai tham số cụ thể được thay thế, sau đó URI được sử dụng để tìm nạp ô.

Vì đây là javascript, tôi muốn tìm URI được lưu trong bộ nhớ cache và thay thế bằng một hàm, thay vì tạo động URI và trả về nó.

Tôi không cần phải làm điều này mỗi lần chạy, chỉ muốn và ý tưởng về nơi tài sản đang được lưu trữ, vì vậy tôi có thể viết mã để hax0r nó.

Câu hỏi gốc

Nếu tôi đặt URI để một số giá trị như "floobieblaster", khi tôi đặt một breakpoint, tôi có thể tìm kiếm các đối tượng javascript đệ quy cho "floobieblaster" và nhận được tài sản đó được lưu trữ mà giá trị?

Chỉnh sửa để thêm

Đối tượng tôi đang tìm kiếm dường như có một tham chiếu vòng tròn, do đó bất kỳ mã đệ quy có thể sẽ gây ra một stackoverflow.

Có bất kỳ thủ thuật trình chỉnh sửa/trình gỡ lỗi nào tôi có thể sử dụng không?

+0

Tôi nghĩ rằng tôi có khả năng có thể đổ vật ra json và tìm kiếm nó như vậy. Có lẽ có một cách tốt hơn? Hình như đối tượng có cấu trúc tròn. – Alan

+0

Thư viện của Crockford (xem cycle.js) https://github.com/douglascrockford/JSON-js hỗ trợ mã hóa và giải mã các đối tượng hình tròn thành json (+ jsonpath). Bạn có thể nối tiếp và tìm kiếm như bạn đã đề xuất hoặc chỉ cần thay đổi mã một chút để đạt được mục tiêu của bạn trực tiếp. – davin

Trả lời

20

Something đơn giản như thế này nên làm việc:

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); 
     } 

    } 

} 

Nếu bạn thực hiện searchObj(testObj, 'testValue'); nó sẽ đăng nhập sau ra cửa sổ Console:

property=test value=testValue 
property=test2a value=testValue 

Rõ ràng, bạn có thể thay thế các console.log với bất cứ điều gì bạn muốn, hoặc thêm tham số gọi lại vào hàm searchObj để làm cho nó có thể sử dụng lại được.

EDIT: Nhập tham số query cho phép bạn chỉ định giá trị bạn muốn tìm kiếm khi bạn gọi hàm.

+6

+1 nhưng để tránh tìm kiếm các đối tượng trên chuỗi '[[Prototype]]', cần có một phép thử 'hasOwnProperty'. Xem xét thử nghiệm cho 'typeof obj [key] == 'function'' quá. – RobG

2

Đây là giải pháp của tôi, nó phù hợp với chuỗi/giá trị đã cho với phép thử regex và trả về mảng phù hợp.Nó không đệ quy, tuy nhiên bạn đã loại bỏ điều này khỏi câu hỏi của bạn.

Đây là từ câu trả lời của tôi tại các chủ đề sau: Search a JavaScript object

nguyên tắc tương tự, như những người khác đã gợi ý - tìm kiếm một đối tượng cho giá trị nhất định, cho bất cứ ai để tìm kiếm giải pháp này.

Chức năng:

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; 
} 

Đối tượng của bạn:

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

Đối với việc sử dụng:

(Điều này sẽ tìm kiếm mảng myObject.elems của bạn cho một 'tên' phù hợp 'FC')

var matched = myObject.elems.findValue('name', 'FC'); 
console.log(matched); 

Kết quả - kiểm tra bảng điều khiển của bạn:

[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] 

Nếu bạn muốn khớp chính xác, bạn chỉ cần thay đổi regex trong tuyên bố ba thành giá trị cơ bản khớp. tức là

v[name] === value ? v : null 
2

Chức năng này sẽ tìm trong đối tượng. Nó sẽ khớp với Truy vấn tìm kiếm với mọi thuộc tính của đối tượng.Điều này hữu ích khi bạn cần tìm kiếm trong đối tượng đa chiều Sau khi bỏ ra hàng giờ, tôi nhận được mã này từ Dự án AngularJS của Google.

/* 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; 
} 
}; 
+1

Điều này dường như xử lý các cấu trúc đệ quy, mà câu trả lời được chấp nhận thì không. – Automatico

1

Đây là một ready-to-go phương pháp tĩnh dựa trên cách tiếp cận Bryan thuận tiện hơn:

/** 
* 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; 
} 

Đối với một đối tượng

var testObj = { 
    test: 'testValue', 
    test1: 'testValue1', 
    test2: { 
     test2a: 'testValue', 
     test2b: 'testValue1' 
    } 
} 

sẽ dẫn đến

["test", "test2.test2a"] 
0

Tôi đã chỉnh sửa câu trả lời của Bryan Downing để in một bản hierarc hy cho các đối tượng sâu:

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; 
} 

Sau đó, chạy searchObj(testObj, 'testValue');

0
//example from the Binance API. 
//They return a ticker object with ALL of their currency pairs 
//that contain the current price of each pair. 
//We want to allow users to enter in a currency pair, 
//and return the current ask price of the currency. E.g., 
//users are asking for something that we do not know if it 
// exists until the ticker object is returned. Therefore, we 
//must search for a property in the object, if it exists, 
//return the value of the found property. 

let symbol = 'LTCBTC'; 
if (symbol in ticker) { 
    console.log(ticker[symbol]); 
} else { 
console.log('symbol not found or not supported'); 
} 
//This example uses the javascript property accessor to access 
//the property once we've verified it is in the 
//object [js property accessors][1] and the in 
//operator [js in property][2] 
Các vấn đề liên quan