未捕获的TypeError:无法读取属性 - 尽管属性存在

时间:2013-03-07 16:43:37

标签: javascript

var sorted = DocumentListData.Documents.sort(function (a, b) {
    var nameA = a.Document.toLowerCase(),
        nameB = b.Document.toLowerCase();

    return nameA.localeCompare(nameB);
});

for (var i = 0, len = sorted.length; i < len; i++) {

    if (sorted[i].Document=== 'abc') {
        sorted.splice(i, 1);
    }

    if (sorted[i].Document=== 'xyz') {
        sorted.splice(i, 1);
    }
}

我只是在这里犯了一个小时的错误。虽然Document属性存在,但它会抛出Document未定义。

Uncaught TypeError: Cannot read property 'Document' of undefined。当我删除sorted.splice(i,1)时,它可以工作,并且没有错误。

2 个答案:

答案 0 :(得分:4)

您正在修改正在迭代的数组。 splice(i,1)删除第i个元素。当您拼接已排序的数组时,您将删除元素,因此最终会超过数组的长度,因为循环将转到数组的原始长度。然后sorted[i]未定义,您将收到您正在描述的错误。

通常,修改当前正以这种方式迭代的数组永远不是一个好主意。如果必须这样做,请确保包括检查以查看i不是>=到当前数组的长度。但是使用while循环可能更适合这里。

var counter =0;
while(counter < sorted.length) {
var doc = sorted[counter].Document;
  if (doc === 'abc' ||doc === 'xyz') {
    sorted.splice(counter, 1);
  }
  else{
   counter++;
  }
}

还有一些想法

  1. document是javascript浏览器环境中的预定义变量,通常JS有一个约定,大写变量仅用于构造函数。所以Document可能不是一个很好的属性名称选择。

  2. 如果您不需要支持旧版本的IE,您也可以将Array.Prototype.filter作为一种更干净的方式来实现您的目标

答案 1 :(得分:2)

如果最后一个元素的Documentabc,则会在第一个if条件中将其删除。

sorted[i]将成为undefined(因为您删除了最后一个元素),当第二个if运行时,您将收到您正在描述的错误。< / p>

您可以使用else if

解决此问题
if (sorted[i].Document=== 'abc') {
    sorted.splice(i, 1);
} else if (sorted[i].Document=== 'xyz') {
    sorted.splice(i, 1);
}