未捕获的类型错误:不能读取属性-尽管属性存在

Uncaught TypeError: Cannot read property - Though property exists

本文关键字:属性 读取 存在 不能读 不能 类型 错误      更新时间:2023-09-26
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是undefined。

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

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

一般来说,以这种方式修改当前正在迭代的数组绝对不是一个好主意。如果您必须这样做,请确保包含If检查,以查看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作为一种更干净的方式来做你想做的事情

如果最后一个元素的Documentabc,它将在第一个if条件下被删除。

sorted[i]将变成undefined(因为你已经删除了最后一个元素),当第二个if运行时,你会得到你所描述的错误。

你可以使用else if:

来修复这个问题
if (sorted[i].Document=== 'abc') {
    sorted.splice(i, 1);
} else if (sorted[i].Document=== 'xyz') {
    sorted.splice(i, 1);
}