“闭包”如何影响我在jQuery中对dom节点的嵌套遍历?

时间:2011-08-18 18:17:00

标签: javascript jquery pointers

我理解有些闭合,但有时我似乎无法做到正确。我相信这是罪魁祸首...因为我正在穿越,我不确定关闭是否必要或可能。

所以我必须解析一些看起来像这样的外部标记:

<h2>Fried Calamari</h2>
<dd>Price:$8.95</dd>
<dd>Pan-fried calamari served with our delicious homemade tomato sauce.</dd>
<h3>Extra Sauce</h3>
<dd>Required:0 / Up To:99</dd>
<ol>
<li><dt>Extra Sauce</dt><dd>Price:$0.99</dd></li>
</ol>
<h2>Fried Zuchinni</h2>
<dd>Price:$6.95</dd>
<dd>Tossed with garlic and herbs. Served with a side of tomato sauce.</dd>
<h3>Extra Sauce</h3>
<dd>Required:0 / Up To:99</dd>
<ol>
<li><dt>Extra Sauce</dt><dd>Price:$0.99</dd></li>
</ol>
<h2>Eggplant Rollatini Appetizer</h2>
<dd>Price:$7.95</dd>
<dd>Fresh rolled eggplant filled with Ricotta and topped with tomato sauce and melted Mozzarella.</dd>
<h3>Extra Sauce</h3>
<dd>Required:0 / Up To:99</dd>
<ol>
<li><dt>Extra Sauce</dt><dd>Price:$0.99</dd></li>
</ol>
<h2>Mozzarella Sticks</h2>
<dd>Price:$6.95</dd>
<dd>Classic Mozzarella sticks served with a side of tomato sauce.</dd>
<h3>Extra Sauce</h3>
<dd>Required:0 / Up To:99</dd>
<ol>
<li><dt>Extra Sauce</dt><dd>Price:$0.99</dd></li>
</ol>
<h2>Buffalo Rock Shrimp</h2>
<dd>Price:$9.75</dd>
<dd>Crispy rock shrimp toasted in our signature buffalo sauce. Served with Blue cheese crumbles.</dd>
<h3>Extra Dressing</h3>
<dd>Required:0 / Up To:99</dd>
<ol>
<li><dt>Extra Dressing</dt><dd>Price:$0.99</dd></li>
</ol>

这是我的js使用jQuery ...

$(document).ready(function(){

 $('h2').each(function(i) {
     //to hold the info
     var itemDetail = new Object();
     //h2's contain the name
     itemDetail['name'] = $(this).html();       

     // but dd's contain price description and other
     // and we need to traverse all <dd> tags for each <h2> 
     $(this).siblings('dd').each(function(){             
         var itemInfo = $(this).html();
         var priceLabel = itemInfo.slice(0,7);
         var priceValue = itemInfo.slice(7);
         if (priceLabel='Price:$'){
             itemDetail['price'] = priceValue;
         }else{
             // discard required info (leaving description)
             if (itemInfo.slice(0,9) != 'Required:')
             //descriptions don't have a label 
             itemDetail['description'] = itemInfo;
         }
     });
     console.log(itemDetail)
 }); 
}); 

如果我在priceLabel和priceValue上使用alert()逐步遍历遍历,则逻辑echo是正确的值(具体来说priceValue是一个数字,当priceLabel符合条件时,但是当我记录对象时,我没有得到每个内部遍历的迭代。相反,priceLabel等于最终迭代的.slice()。

有没有更好的方法来避免这种情况或使用闭包来强制信息进入我的对象......

2 个答案:

答案 0 :(得分:3)

有几个问题:

  • =执行作业,但您使用它进行比较,而不是使用=====
  • 您使用了.siblings('dd'),它为您提供所有 dd元素,而不仅仅是下一个相邻元素。使用当前标记,您可以使用nextUntil(':not(dd)')代替。
 $('h2').each(function(i) {
     var itemDetail = new Object();
     itemDetail['name'] = $(this).html();       

       // ----v---get next siblings of "h2" until on that is not "dd" is reached
     $(this).nextUntil(':not(dd)').each(function(){             
         var itemInfo = $(this).html();
         var priceLabel = itemInfo.slice(0,7);
         var priceValue = itemInfo.slice(7);

              //--------v----------- use == instead of =
         if (priceLabel == 'Price:$'){
             itemDetail['price'] = priceValue;
         }else{
             if (itemInfo.slice(0,9) != 'Required:')
             itemDetail['description'] = itemInfo;
         }
     });
     console.log(itemDetail)
 }); 

修改

如果你的标记与它显示的方式一致,那么你可以将代码缩短一点:

 $('h2').each(function(i) {
     var itemDetail = new Object();
     itemDetail['name'] = $(this).html();       

     var dds = $(this).nextUntil(":not(dd)");
     itemDetail['price'] = dds.eq(0).html().slice(7);
     itemDetail['description'] = dds.eq(1).html();
     console.log(itemDetail);
 }); 

甚至更短的使用对象文字:

 $('h2').each(function(i) {
     var dds = $(this).nextUntil(":not(dd)");
     var itemDetail = {
                name: $(this).html(),
               price: dds.eq(0).html().slice(7),
         description: dds.eq(1).html()
     };
     console.log(itemDetail);
 }); 

答案 1 :(得分:1)

由于您在第一个.each中传递的函数内声明了itemDetail,因此其范围仅限于该函数(以及您在该函数中所执行的函数)。

另外,当你逐步浏览$(this).siblings('dd')时,你一遍又一遍地覆盖itemDetail ['price']和itemDetail ['description'],这是故意的吗?