2009-07-17 57 views
6

我刚开始使用jQuery,我非常喜欢使用选择器。我发现这个习惯用法是遍历对象树的非常好的方法(例如,JSON查询结果)。举例来说,如果我有这样的对象:jquery选择器的纯JavaScript对象,而不是DOM元素

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

我希望能够写类似$(“孩子巴兹:去年”,OBJ)并获得5.我承认,链接不会工作,但我仍然喜欢选择运算符。任何人都知道这样的野兽是否存在,或者写一个最简单的方法是什么?

+0

使用jQuery包裹的元素,然后循环正是在那里,你不喜欢obj.child.baz理由[obj.child.baz.length -1]; ? – 2009-07-17 16:40:46

+0

对于这个玩具的例子来说,它可以工作,但是对于更深的树木和更大的物体很快就会崩溃。例如,我正在研究一个使用树代表网络数据包的程序,并且我希望能够编写$('icmp [code = UNREACHABLE]'数据包列表)来获取ICMP帧以供不可达数据包使用。 – brendan 2009-07-17 16:46:10

回答

5

这里是一个概念验证实现获取jQuery本身的工作对象。通过对象包装(FakeNode),你可以欺骗的jQuery到使用其内置的纯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)); 
} 

而且用法是:

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

给输出:

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

当然,你必须实现比以上更多的支持更复杂的选择器。

顺便说一句,你见过jLinq

0

数组对象有一些方法,您可以使用:

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

一些其他的例子:

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

谢谢。是的,这与我现在的工作有关。但在我看来,选择器更强大,因为您不必知道您正在走路的特定对象的确切形状,以便找到有趣的元素。我认为有一个很好的理由jQuery不会让你做html.body.table [1] .tr ... – brendan 2009-07-17 16:52:09

0

嗯,我个人说,纯粹的对象访问看起来比jQuery的一样好查询。有一件事情会很整齐,就是切片和其他过滤技术。

如果你真的想和对象访问查询玩,下面是一些可能(认为的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. 

在比赛的最后阶段,我看不出这是非常有用的。但呃,这是一个想法,我猜=)

0

简单,最简单的方法是通过每个

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); 
} 
}); 
相关问题