0

我制作了一些 jQuery 插件——它们都解析 JSON 提要并使用 Mustache.js 渲染它们;每个插件都采用一个整数值来表示要显示的项目数。

Uncaught TypeError: Cannot read property 'link' of undefined在尝试使用以下代码解析 Stack Overflow JSON 提要时收到一条消息:

   $.ajax({
      type: 'GET',
      url: query,
      contentType: "jsonp",
      dataType: 'jsonp',
      success: function (jsonp) {

        /* loop through JSON items converting the time from UNIX timestamp
         ** format to readable words by parsing it through timeConverter() */
        var i;
        for (i = 0; i < jsonp.items.length; i++) {
          if (i > num-1){
            delete jsonp.items[i];
          } else {
            jsonp.items[i].creation_date = timeConverter(jsonp.items[i].creation_date);
          }
        }


        var output = Mustache.render(must_template, jsonp);
        element.html(output);
        return element;
      } //EOF CALLBACK
    }); //EOF AJAX

作为一个快速修复,我通过简单地注释掉delete操作来禁用截断。该错误表明 Mustache.js 正在尝试访问不再存在的 JSON 对象的一部分;然而,该delete操作显然只影响超出用户定义限制的项目。

发生此行为时,数组中仍有 20 个项目。

注意: 是的,我自己回答了这个问题;但是 - 如果它显示最佳实践,更简洁的方式或以某种方式改进我的答案,我非常愿意接受另一个答案。:)

4

3 回答 3

1

经过多次谷歌搜索,我什么也找不到,甚至 StackOverflow 也让我失望了。然后,偶然地,我遇到了我的“快速破解”注释掉删除行的这种意想不到的副作用。

http://i50.tinypic.com/2ecgnxz.png

由于我没有注释掉整个if/else块,我的timeConverter()函数没有在通常会被删除的项目上运行。这证实了for()和的组合if(){} / else{}工作正常。所以看起来 Mustache.js 试图访问已经被删除的项目!几乎就像在删除项目时没有更新数组的length属性一样。items[]

我做了一个jsFiddle测试用例,这证实了问题所在。这是代码和输出:

    $.ajax({
      type: 'GET',
      url: query,
      contentType: "jsonp",
      dataType: 'jsonp',
      success: function (jsonp) {

        /* loop through JSON items converting the time from UNIX timestamp
         ** format to readable words by parsing it through timeConverter() */
        var i;
        for (i = 0; i < jsonp.items.length; i++) {
          if (i > num-1){
              console.log("Deleting item. Current Count: "+jsonp.items.length);
            delete jsonp.items[i];
              console.log("Deleting item. New Count: "+jsonp.items.length);
          } else {
            jsonp.items[i].creation_date = timeConverter(jsonp.items[i].creation_date);
          }
        }
        console.log(jsonp);
        return element;
      } //EOF CALLBACK
    }); //EOF AJAX

http://i45.tinypic.com/546kgj.png

我尝试快速修复使用计数器来计算每次删除,然后从length属性(jsFiddle)中减去删除计数器:

        $.ajax({
          type: 'GET',
          url: query,
          contentType: "jsonp",
          dataType: 'jsonp',
          success: function (jsonp) {

            /* loop through JSON items converting the time from UNIX timestamp
             ** format to readable words by parsing it through timeConverter() */
            var i, deleted = 0;
            for (i = 0; i < jsonp.items.length; i++) {
              if (i > num-1){
                delete jsonp.items[i];
                deleted++;
              } else {
                jsonp.items[i].creation_date = timeConverter(jsonp.items[i].creation_date);
              }
            }
            jsonp.items.length -= deleted;
            console.log(jsonp);
            return element;
          } //EOF CALLBACK
        }); //EOF AJAX

这是生成的输出:

http://i45.tinypic.com/vg69vo.png

这段代码在放回测试环境并与 Mustache.js 一起使用时运行良好。在数组上使用时,使用 delete 关键字不会影响长度属性

来自 Java 背景,我认为这是一个属性而不是函数这一事实是理所当然的length——因此它不会在对数组进行任何更改时进行更新。一个愚蠢的错误让我花费了比它应该更多的时间!但是,我找不到任何其他关于此的帖子,所以我想我会发布它,希望它可以帮助处于类似位置的其他人!

于 2012-11-21T11:16:12.017 回答
1

delete与数组相比,是“低级”运算符。它直接删除object 属性,绕过所有特定的数组逻辑,因此不会更新数组的长度。

如果要从数组中删除元素,请使用.splice [MDN] ,或者在您的情况下,您可以简单地设置数组的长度并在之后迭代剩余的元素:

jsonp.items.length = Math.min(num, jsonp.items.length);
for (i = 0; i < jsonp.items.length; i++) {
  jsonp.items[i].creation_date = timeConverter(jsonp.items[i].creation_date);
}
于 2012-11-21T11:41:39.303 回答
1

删除并没有像您已经发现的那样更改数组计数,它只是删除键。要从数组中删除项目,您可以使用 splice。例子:

var array2 = [ 1, 2, 3, 4 ];
array2.splice(2, 1);

console.log('---------------------------');
console.log(array2.length); // 3
console.log(array2[0]); // 1
console.log(array2[1]); // 2
console.log(array2[2]); // 4
console.log(array2[3]); // undefined

工作样本:http: //jsfiddle.net/qbXjp/1/

于 2012-11-21T11:42:22.057 回答