You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JS异步请求构建嵌套对象异常,为何出现自引用结构?

问题:JSON数据构建嵌套对象出现自引用异常

我是JavaScript新手,在尝试从JSON文件获取数据构建嵌套对象时,发现生成的对象出现了自引用的异常结构。但手动构建相同结构的嵌套对象时,结果完全正常。

我的实现代码如下:

function fetchJson(name) {
var dico = {};
fetch('../json/' + name + '.json')
    .then(response => response.json())
    .then(data => {
        for (var x in data) {
            if(!isClubExist(dico, data[x].Club)) { // 判断俱乐部是否已存在于对象中
                addClub(dico, data[x].Club);
            }
            addPlayer(dico, data[x].Club, data[x].Poste, fullName(data[x].Nom, data[x].Prénom));
        }
})
return dico;
}

手动构建的示例代码:

var subjectObject = {
    "Front-end": {
      "HTML": ["Links", "Images", "Tables", "Lists"],
      "CSS": ["Borders", "Margins", "Backgrounds", "Float"]
    },
    "Back-end": {
      "PHP": ["Variables", "Strings", "Arrays"],
      "SQL": ["SELECT", "UPDATE", "DELETE"]
    }
}
                        
console.log(subjectObject);

问题原因及解决方法

1. 异步时序问题(核心问题)

fetch是异步操作,你调用fetchJson后会立刻返回空的dico对象,此时then回调里的填充逻辑还没执行。如果后续你直接打印这个dico,浏览器控制台可能因为引用特性显示后续修改后的状态,但这会导致你误以为对象结构有问题,同时也无法正确拿到填充完成的数据。

修正方式:让函数返回Promise,用async/await或then获取最终结果:

async function fetchJson(name) {
    var dico = {};
    const response = await fetch('../json/' + name + '.json');
    const data = await response.json();
    for (let x in data) { // 把var换成let,避免潜在作用域问题
        if(!isClubExist(dico, data[x].Club)) {
            addClub(dico, data[x].Club);
        }
        addPlayer(dico, data[x].Club, data[x].Poste, fullName(data[x].Nom, data[x].Prénom));
    }
    return dico;
}

// 使用示例
fetchJson('你的文件名').then(dico => {
    console.log(dico); // 这里才能拿到正确填充后的对象
});

2. 辅助函数的逻辑错误(自引用的直接原因)

自引用异常大概率是addClub或addPlayer的实现写错了,比如不小心把dico本身赋值给了内部属性。

正确的辅助函数示例:

// 判断俱乐部是否存在
function isClubExist(dico, clubName) {
    return !!dico[clubName];
}

// 添加俱乐部:创建新的空对象,而非赋值dico本身
function addClub(dico, clubName) {
    dico[clubName] = {};
}

// 添加球员:按职位分类存入数组
function addPlayer(dico, clubName, position, fullName) {
    if (!dico[clubName][position]) {
        dico[clubName][position] = [];
    }
    dico[clubName][position].push(fullName);
}

// 拼接全名
function fullName(lastName, firstName) {
    return `${firstName} ${lastName}`;
}

内容的提问来源于stack exchange,提问作者Hezaerd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 13:48:21