我有一些jQuery插件 - 所有解析JSON提要并使用Mustache.js渲染它们;每个插件都会显示要显示的项目的整数值。
尝试使用以下代码解析Stack Overflow JSON Feed时收到了Uncaught TypeError: Cannot read property 'link' of undefined
:
$.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
作为quickfix,我通过简单地注释掉delete
操作来禁用截断。该错误表明Mustache.js正在尝试访问不再存在的JSON对象的一部分;但delete
操作显然只会影响超出用户定义限制的项目。
发生此行为时,数组中仍有20个项目。
注意: 是的,我自己已经回答了这个问题;然而 - 如果它表现出最佳实践,更简洁的方式或以某种方式改善我的答案,我更愿意接受另一个答案。 :)
答案 0 :(得分:1)
经过大量的谷歌搜索后,我找不到任何东西,甚至StackOverflow都让我失望了。然后,偶然的机会,我偶然发现了我的'快速黑客'的意外副作用,评论了删除行..
http://i50.tinypic.com/2ecgnxz.png 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 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 http://i45.tinypic.com/vg69vo.png
此代码在放回测试环境并与Mustache.js一起使用时运行正常。 使用delete关键字在数组上使用时不会影响length属性
来自Java背景我理所当然地认为length
是属性而不是函数 - 因此在对数组进行任何更改时不会更新。一个愚蠢的错误让我花费的时间比应该花的多!但是,我找不到任何关于此的帖子,所以我想我会发布它,希望它能帮助其他类似职位的人!
答案 1 :(得分: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);
}
答案 2 :(得分: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