JavaScript操作JSON数据传参调用函数问题解决方案
代码错误修正与功能实现
原代码核心问题梳理
- 属性名大小写不匹配:JSON数据根节点专辑集合key为
Albums(首字母大写),原代码多处误写为小写albums,导致属性读取失败 - forEach遍历调用计算函数时未传入遍历得到的专辑名参数
- 对JSON结构理解错误:
tracks数组存储的是包含title/src/dur的对象,不是纯字符串,原代码直接把遍历项当成字符串/索引使用 getTrackSeconds函数路径访问错误,没有做曲目标题匹配逻辑,直接访问不存在的嵌套属性导致报错
各需求对应实现逻辑
- 需求1(forEach遍历传参):遍历
Object.keys(data.Albums)得到的o就是专辑名key,直接作为入参传入getAlbumDuration(o)即可 - 需求2(专辑曲目遍历统计):传入专辑名后,通过
data.Albums[album].tracks取到该专辑下所有曲目数组,遍历数组即可完成曲目总数统计、时长累加等操作,注意每个遍历项是曲目对象,需通过.title取曲目标题 - 需求3(标题匹配时长):遍历目标专辑的tracks数组,判断当前项
title是否和传入的曲目标题一致,匹配成功后取该项的dur字段做时间格式转换,返回总秒数即可
修正后完整代码
let data = await JsonData("jukebox.json"); // 填充下拉选择框选项 Object.keys(data.Albums).forEach((o)=>{ const artistOption = document.createElement('option'); // 传入遍历得到的专辑名o计算总时长 let albumDur = getAlbumDuration(o); // 可自行拼接显示总时长,可额外写函数把秒转成x:xx格式优化展示 artistOption.innerText = `${o} (总时长:${albumDur}秒,共${data.Albums[o].tracks.length}首)`; artistOption.value = o; document.getElementById("artistSelector").appendChild(artistOption); }); /** * 计算指定专辑总时长(单位:秒) * @param {string} album 专辑名key * @returns {number} 专辑总秒数 */ function getAlbumDuration(album) { let totalSeconds = 0; const trackList = data.Albums[album].tracks; // 遍历专辑下所有曲目累加时长 for (const trackItem of trackList) { // 传入曲目标题计算单首秒数 let seconds = getTrackSeconds(album, trackItem.title); totalSeconds += seconds; } return totalSeconds; } /** * 根据专辑名、曲目标题匹配返回单首曲目时长(单位:秒) * @param {string} album 所属专辑名 * @param {string} trackTitle 曲目标题 * @returns {number} 单首曲目总秒数 */ function getTrackSeconds(album, trackTitle) { const trackList = data.Albums[album].tracks; // 遍历匹配标题一致的曲目 for (const track of trackList) { if (track.title === trackTitle) { const time = track.dur.split(":"); const minutes = parseInt(time[0], 10); const seconds = parseInt(time[1], 10); return minutes * 60 + seconds; } } // 匹配不到返回0,可按需添加异常处理逻辑 return 0; }
补充说明
如果需要单独获取指定专辑的曲目总数,直接取data.Albums[对应专辑名].tracks.length即可,不需要额外遍历。如果需要做跨专辑的全局曲目匹配,可以去掉getTrackSeconds的album参数,遍历所有专辑下的tracks做匹配即可。
内容的提问来源于stack exchange,提问作者Robin
相关产品推荐
相关产品推荐

