0

私が作成したいくつかの jQuery プラグインがあります。すべて JSON フィードを解析し、Mustache.js を使用してレンダリングします。各プラグインは、表示する項目数の整数値を取ります。

Uncaught TypeError: Cannot read property 'link' of undefined次のコードを使用してスタック オーバーフロー 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配列に比べて「低レベル」の演算子です。オブジェクトのプロパティを直接削除し、特定の配列ロジックをすべてバイパスするため、配列の長さは更新されません。

.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

すでにわかっているように、削除は配列数を変更していません。キーを削除するだけです。配列からアイテムを削除するには、スプライスを使用できます。例:

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 に答える