2012-01-11 22 views
48

thể trùng lặp:
Accessing nested JavaScript objects with string keyJavascript: Nhận giá trị sâu từ đối tượng bằng cách đi qua đường dẫn đến nó như là chuỗi

Có lẽ danh hiệu là không đủ rõ ràng, tôi chỉ không biết làm thế nào để xác định những gì tôi đang tìm kiếm và tiếng Anh của tôi thực sự tệ, xin lỗi.

Tôi đang cố gắng tạo hàm trả về giá trị đối tượng, nhưng cũng phát đẹp với các đối tượng lồng nhau. Ví dụ:

var obj = { 
    foo: { bar: 'baz' } 
}; 

Tôi muốn truy cập giá trị của obj.foo.bar bằng cách đặt chuỗi "foo.bar" vào hàm.

function(obj, path) { 
    // Path can be "foo.bar", or just "foo". 
} 

Cảm ơn!

+0

này hiện đang được hỗ trợ bởi lodash sử dụng _.get (obj, tài sản). Xem https://lodash.com/docs#get –

+0

Vì câu hỏi này đã được đánh dấu là Bản sao (ngay cả khi không phải) tôi phải trả lời trong nhận xét. Bạn có thể sử dụng ECMAScript6 Destructuring: 'var obj = {foo: {bar: 'baz'}}; ({foo: {bar: value}} = obj); console.log (giá trị);' – Alexander

Trả lời

37

Hãy xem xét điều này:

var obj = { 
    foo: { bar: 'baz' } 
}; 

function deepFind(obj, path) { 
    var paths = path.split('.') 
    , current = obj 
    , i; 

    for (i = 0; i < paths.length; ++i) { 
    if (current[paths[i]] == undefined) { 
     return undefined; 
    } else { 
     current = current[paths[i]]; 
    } 
    } 
    return current; 
} 

console.log(deepFind(obj, 'foo.bar')) 
+5

@ 7elephant và qiao: Fails (ném lỗi) nếu bất kỳ phần nào của đường dẫn đánh giá ' null'. Đó có thể là một tính năng hoặc một lỗi, tùy thuộc vào quan điểm của bạn. :-) –

3

Bạn muốn chia chuỗi trên chấm và sau đó liên tục lập chỉ mục vào đối tượng, ví dụ: dọc theo dòng:

function goDeep(obj, path) { 
    var parts = path.split('.'), 
     rv, 
     index; 
    for (rv = obj, index = 0; rv && index < parts.length; ++index) { 
     rv = rv[parts[index]]; 
    } 
    return rv; 
} 

Live example

đó làm việc vì bạn có thể truy cập vào tài sản của một đối tượng trong một vài cách khác nhau: Có chấm cú pháp sử dụng một chữ (obj.foo), và có được phơi sáng cú pháp sử dụng một chuỗi (obj["foo"]). Trong trường hợp sau, chuỗi có thể là kết quả của bất kỳ biểu thức nào, nó không phải là một chuỗi ký tự. Trong trong tất cả các, rv được thiết lập với giá trị như nhau:

rv = obj.foo.bar; 
// Or 
rv = obj.foo["bar"]; 
// Or 
f = "foo"; 
rv = obj[f].bar; 
// Or 
s = "b"; 
rv = obj.foo[s + "ar"]; 
+1

Chắc chắn, yêu cầu là không thể hiện, nhưng có lẽ chúng ta không nghi ngờ rằng OP có thể cũng muốn một cuộc gọi chức năng như 'goDeep (myObj, 'bar [3] .baz')'? Điều đó có thể nằm ngoài phạm vi cho câu hỏi hiện tại ... –

+1

@DavidHedlund: Điểm công bằng, cũng có thể hữu ích khi kiểm tra biểu mẫu có ngoặc trong mỗi phần 'để hoàn toàn tương thích với cú pháp của riêng JavaScript.Tôi sẽ để nó như một bài tập cho OP. :-) –

+0

(Vâng, không * hoàn toàn *, để làm điều đó bạn phải về cơ bản tái phát minh [hoặc -shudder- sử dụng] 'eval'. Nhưng nói, chủ yếu là tương thích với.) –

5

cái gì đó như:

function(obj, path) { 
    var current=obj; 
    path.split('.').forEach(function(p){ current = current[p]; }); 
    return current; 
} 
+0

http://meta.stackexchange.com/a/118023/134069 –

58

này hoạt động một cách chính xác:

var deep_value = function(obj, path){ 
    for (var i=0, path=path.split('.'), len=path.length; i<len; i++){ 
     obj = obj[path[i]]; 
    }; 
    return obj; 
}; 

Đây là chuyên gia/demo: jsfiddle.net/tadeck/5Pt2q/13/

EDIT: Tôi đã xóa các biến dư thừa, rút ​​ngắn mã.

+1

đẹp. tốt hơn bất kỳ thứ gì trong http://stackoverflow.com/questions/6491463/accessing-nested-javascript-objects-with-string-key –

+0

được mở rộng để hỗ trợ mảng. http://jsfiddle.net/5Pt2q/20/ –

+3

@SteveBlack tốt hơn như thế nào? Nó hỗ trợ một cú pháp bị hạn chế hơn và không có kiểm tra lỗi cho việc cố gắng giải quyết một khóa không tồn tại. – Alnitak

7

Bạn có ý nghĩa như thế này? Đây là một phiên bản đệ quy

function recLookup(obj, path) { 
    parts = path.split("."); 
    if (parts.length==1){ 
     return obj[parts[0]]; 
    } 
    return recLookup(obj[parts[0]], parts.slice(1).join(".")); 
} 

Xem http://jsfiddle.net/kExSr/

+0

VÀNG! Tôi đã có thể sử dụng điều này để ánh xạ một đường dẫn/Root [1]/This/làm việc với một đối tượng {"Root [1]": Giá trị {work: "này"}}. đã phải cắt hàng đầu/và thay đổi. đến/nhưng nếu không thì đẹp. –

+1

điều này không quá nhanh. Không nên tham gia() các đường dẫn một lần nữa, chỉ cần kiểm tra nếu đường dẫn là một chuỗi hoặc một mảng – Jonathan

Các vấn đề liên quan