开发者问题收集

使用动态键访问 JSON 是可行的,但也会引发错误“无法读取未定义的属性”

2017-05-18
331

我一直在寻找答案,但没有发现其他人提到过这样的问题。我尝试了几种变体和潜在解决方案,但都无济于事。

我有以下 JSON 文件:

{
    "subpatterns": {
        "sub1": {
            "selected": "V",
            // other properties not important for this example
        },
        "sub2": {
            "selected": "C",
            // other properties not important for this example
        },
        "sub3": {
            "selected": "N",
            // other properties not important for this example
        }
    },
    // other properties not important for this example
}

然后我使用以下代码访问该数据并对“子模式”下的每个键调用一个函数:

subPs.startup = function () {
    function addStartData() {
        for (var i = 1; i <= Object.keys(subPs.data.subpatterns).length + 1; i++) {
            subPs.addRow(); // I want to add one more row than the amount of data I have (i.e. one blank row at the end), which is why the for loop is .length + 1
            var selected = subPs.data.subpatterns["sub" + i].selected; // This is where it throws the error
            console.log(selected); // But this works
            if (selected !== undefined) {
                subPs.selectSub(i, selected); // And this works, too
            }
        }
        subPs.checkDupes();
    }
    var json = $.getJSON("../data/gen.json", function (json) {
            subPs.data = json;
            addStartData();
    });
};

代码执行正确。函数 subPs.addRow()subPs.selectSub() 都将正确的数据添加到 DOM,包括来自 JSON/变量 selected 的信息。此外,调用 console.log(selected) 会记录正确的结果。然而控制台却记录了一个错误:

Uncaught TypeError: Cannot read property 'selected' of undefined
    at addStartData (gen.js:28)
    at Object.success (gen.js:41)
    at i (jquery-3.2.1.min.js:2)
    at Object.fireWith [as resolveWith] (jquery-3.2.1.min.js:2)
    at A (jquery-3.2.1.min.js:4)
    at XMLHttpRequest.<anonymous> (jquery-3.2.1.min.js:4)

为什么 subPs.data.subpatterns["sub" + i] 未定义,但也能正常工作?我该如何解决这个错误?

我尝试使用 ["sub1"] 而不是使用动态键,但这并没有引发错误。

2个回答

我觉得问题出在 for 循环中,它应该是

for (var i = 1; i <= Object.keys(subPs.data.subpatterns).**length;** i++)

而不是

for (var i = 1; i <= Object.keys(subPs.data.subpatterns).**length + 1**; i++)

因为这将尝试从数组中获取一个以上对象,并且它将始终是 undefined

Sunil Yadav
2017-05-18

我觉得自己像个白痴。显然我只需要睡一觉。

我在变量赋值 之后 检查 subPs.data.subpatterns["sub" + i].selected 是否存在,但我真正需要检查的是变量赋值 之前 检查 subPs.data.subpatterns["sub" + i] 是否存在。

subPs.startup = function () {
    function addStartData() {
        for (var i = 1; i <= Object.keys(subPs.data.subpatterns).length + 1; i++) {
            subPs.addRow(); // I want to add one more row than the amount of data I have (i.e. one blank row at the end), which is why the for loop is .length + 1
            if (subPs.data.subpatterns["sub" + i] !== undefined) { // Putting the variable assignment in this if statement fixed the issue
                var selected = subPs.data.subpatterns["sub" + i].selected;
                subPs.selectSub(i, selected);
            }
        }
        subPs.checkDupes();
    }
    var json = $.getJSON("../data/gen.json", function (json) {
            subPs.data = json;
            addStartData();
    });
};

主要是,我检查了错误的属性是否存在。

nai888
2017-05-18