2009-07-17 40 views
6

Tôi vừa mới bắt đầu sử dụng jquery và tôi thực sự thích sử dụng các bộ chọn. Nó xảy ra với tôi rằng thành ngữ sẽ là một cách rất hay để đi qua cây đối tượng (ví dụ: kết quả truy vấn JSON). Ví dụ, nếu tôi có một đối tượng như thế này:bộ chọn jquery cho các đối tượng javascript đơn giản thay vì các phần tử DOM

var obj = { 'foo': 1, 'bar': 2, 
      'child': { 'baz': [3, 4, 5] } 
      }; 

Tôi rất thích để có thể viết một cái gì đó giống như $ ('baz con: cuối cùng', obj) và nhận 5. Tôi nhận ra rằng chaining được kết sẽ không nhưng tôi vẫn yêu thích toán tử lựa chọn. Bất cứ ai cũng biết nếu một con thú như vậy tồn tại, hoặc cách dễ nhất để viết một cái là gì?

+0

Có một lý do mà bạn không thích obj.child.baz [obj.child.baz.length -1]; ? –

+0

Đó là công việc cho ví dụ đồ chơi này, nhưng phá vỡ nhanh chóng cho cây sâu hơn và các đối tượng lớn hơn. Ví dụ, tôi đang làm việc trên một chương trình sử dụng một cây đại diện cho các gói mạng, và tôi rất muốn có thể viết $ ('icmp [code = UNREACHABLE]', packetlist) để lấy các khung ICMP cho các gói không thể truy cập được. – brendan

Trả lời

5

Đây là cách thực hiện chứng minh khái niệm để giúp jQuery tự hoạt động trên các đối tượng. Qua một wrapper đối tượng (FakeNode), bạn có thể đánh lừa jQuery vào sử dụng nó được xây dựng trong công cụ chọn (sizzle) trên đồng bằng đối tượng JavaScript:

function FakeNode(obj, name, parent) { 
    this.obj = obj; 
    this.nodeName = name; 
    this.nodeType = name ? 1 : 9; // element or document 
    this.parentNode = parent; 
} 

FakeNode.prototype = { 
    documentElement: { nodeName: "fake" }, 

    getElementsByTagName: function (tagName) { 
     var nodes = []; 

     for (var p in this.obj) { 
      var node = new FakeNode(this.obj[p], p, this); 

      if (p === tagName) { 
       nodes.push(node); 
      } 

      Array.prototype.push.apply(nodes, 
       node.getElementsByTagName(tagName)); 
     } 

     return nodes; 
    } 
}; 

function $$(sel, context) { 
    return $(sel, new FakeNode(context)); 
} 

Và việc sử dụng sẽ là:

var obj = { 
    foo: 1, 
    bar: 2, 
    child: { 
     baz: [ 3, 4, 5 ], 
     bar: { 
      bar: 3 
     } 
    } 
}; 

function test(selector) { 
    document.write("Selector: " + selector + "<br>"); 

    $$(selector, obj).each(function() { 
     document.write("- Found: " + this.obj + "<br>"); 
    }); 
} 

test("child baz"); 
test("bar"); 

Cho các đầu ra:

 
Selector: child baz 
- Found: 3,4,5 
Selector: bar 
- Found: 2 
- Found: [object Object] 
- Found: 3 

Tất nhiên, bạn phải thực hiện nhiều hơn những điều trên để hỗ trợ các bộ chọn phức tạp hơn.

BTW, bạn có thấy jLinq không?

+0

Điều đó rất dễ thương, cảm ơn! Và tôi cũng không thấy jLinq. – brendan

+0

Đây là một câu trả lời rất thú vị. – ken

0

Đối tượng mảng có một số phương pháp mà bạn có thể sử dụng:

last = obj.child.baz.slice(-1)[0]; 

Một số ví dụ khác:

first = obj.child.baz.slice(0,1)[0]; 
allExceptFirst = obj.child.baz.slice(1); 
allExceptLast = obj.child.baz.(0,-1); 
+0

Cảm ơn. Vâng, đó là về những gì tôi làm bây giờ. Nhưng các bộ chọn mạnh hơn nhiều theo ý kiến ​​của tôi, bởi vì bạn không phải biết chính xác hình dạng của đối tượng cụ thể mà bạn đang đi để tìm các yếu tố thú vị. Tôi nghĩ rằng có một lý do chính đáng khiến jquery không làm cho bạn làm html.body.table [1] .tr ... – brendan

0

Vâng, tôi muốn đích thân nói rằng tinh khiết truy cập đối tượng trông tốt hơn so với jQuery giống như truy vấn. Một thứ sẽ gọn gàng sẽ được cắt và các kỹ thuật lọc khác.

Nếu bạn thực sự muốn chơi với các truy vấn truy cập đối tượng, sau đây sẽ là một số khả năng (nghĩ XPath):

var obj = { 
    foo: 1, 
    bar: 2, 
    child: { 
     foo: { 
      baz: [3, {a: 1}, {a: 2, b: 3}]}, 
     bar: { 
      baz: [42, {a: 123}, {a: -1}]}, 
     baz: null}}; 

// Implicitly start in the Global object, unless a context is provided. 
// Keys in JavaScript objects are essentially stored in order (not valid for 
// *all* flavors, but it's close to standard. So you could do slicing on keys.) 

// Selects (does not return them) 
// obj.child.foo.baz[1].a 
// obj.child.foo.baz[2].a 
// obj.child.bar.baz[1].a 
// obj.child.bar.baz[2].a 
// Then performs an aggregate that returns value 125. 
$('obj.child[:2].baz[1:].a').sum() 

// Selects obj.foo, obj.bar, obj.child.foo.baz[0] and obj.child.bar.baz[0] 
$('obj *[typeof(number)]') 

// Selects obj.foo and obj.child.foo 
$('obj foo') 

// Other possible methods: delete(), set(), get() (as an array of values), 
// min(), max(), avg(), merge() etc etc. 

Cuối cùng, mặc dù tôi không thấy cách này là rất hữu ích. Nhưng eh, đó là một ý tưởng tôi đoán =)

0

Cách đơn giản nhất và dễ nhất là để bọc các phần tử với jquery và sau đó vòng lặp nó bởi mỗi

var obj = { 'foo': 1, 'bar': 2, 
     'child': { 'baz': [3, 4, 5] } 
     }; 

$(obj).each(function(){ 
console.log(this); 
if(this.hasOwnProperty('foo')) 
{ 
    console.log("hey i found " + this.foo); 
} 
}); 
Các vấn đề liên quan