如何解决链选择未捕获类型错误的问题:无法读取未定义的属性"forEach"



你们能帮我吗? 我尝试编写一个具有 2 级链选择的脚本,但我有这样的错误:

脚本.js:76 未捕获的类型错误:无法读取属性"forEach" 定义

你知道为什么吗? 控制台中显示错误.log最后功能,看起来像这样

捕获的类型错误:无法读取未定义的属性"forEach" 在CMO(脚本.js:76) 在setTown(脚本.js:66) at scripts.js:61 CMO @ scripts.js:76 setTown @ scripts.js:66 (匿名) @ scripts.js:61

这是我的代码

var json = {
"region":{
"Warmińsko - mazurskie":{
"town":{
"Olsztyn":["Mercury", "Novotel","Sheraton", "Radisson", "Gołębiewski"],
"Elbląg": ["Mercury", "Novotel","Sheraton", "Radisson Blue", "Gołębiewski"],
"Iława":["Mer", "Novotel","Sheraton", "Radisson", "Gołębiewski"],
"Ostróda":["Mercury", "Novotel","Mariot", "Radisson", "Gołębiewski"],
"Giżycko":["Mercury", "Novotel","Sheraton", "Vienna House", "Gołębiewski"],
}
},
"Małopolskie":{
"town":{
"Kraków":["Kossak", "Novotel","Sheraton", "Radisson", "Stary"],
"Tarnów":["Mercury", "Novotel","Sheraton", "Tarnovia", "Ibis"],
"Oświęcim":["Mercure", "Golden Tulip","Sheraton", "Radisson", "Hampton"],
"Skała":["Focus", "Novotel","Sheraton", "Radisson", "Zamek"],
"Wieliczka":["Mercurius", "Novotel","Sheraton", "Arche", "Blue Star"],
}
},
"Podlaskie":{
"town":{
"Białystok":["Altus", "Deo","Sheraton", "Radisson Blu", "Aquarion"],
"Suwałki":["Merr", "Novotel","Ibis", "Radisson Red", "Arche"],
"Łomża":["Mercury 2", "Telios","Sheraton", "Blue", "DeSilva"],
"Augustów":["Mariot", "Unicus","Hampton", "Ibis Budget", "Ibis Styles"],
"Zambrów":["Golden", "Blue Star","Sheraton", "Osteria", "Rafles"],
}
},
"Podkarpackie":{
"town":{
"Rzeszów":["Blue Star", "Notel","Radius", "Puławski", "Grębiewski"],
"Jasło":["Mercury2", "Novotel2","Sheraton2", "Radisson2", "Gołębiewski2"],
"Krosno":["Mercury3", "Novotel3","Sheraton3", "Radisson3", "Gołębiewski3"],
"Ustrzyki Górne":["Mercury4", "Novotel4","Sheraton4", "Radisson4", "Gołębiewski"],
"Sanok":["Mercury5", "Novotel5","Sheraton5", "Radisson5", "Gołębiewski5"],
}
},
"Mazowieckie":{
"town":{
"Warszawa":["Mercury6", "Novotel6","Sheraton6", "Radisson6", "Gołębiewski6"],
"Sochaczew":["Mercury7", "Novotel7","Sheraton7", "Radisson7", "Gołębiewski7"],
"Płock":["Mercury8", "Novotel8","Sheraton8", "Radisson8", "Gołębiewski8"],
"Radom":["Mercury9", "Novotel9","Sheraton9", "Radisson9", "Gołębiewski9"],
"Ciechanów":["Mercury0", "Novotel0","Sheraton0", "Radisson0", "Gołębiewski0"],
}
}
}
}
var jsonData = JSON.parse(JSON.stringify(json));
console.log(typeof jsonData);
var region = document.getElementById("region");
var town = document.getElementById("town");
var hotel = document.getElementById("hotel");
let reg = Object.keys(jsonData);
cmo(reg, region);
setTown();
function setTown(){
town.innerHTML = "";
let towns = jsonData[region.value];
cmo(towns, town);
setHotel();
};
function setHotel(){
hotel.innerHTML = "";
let hotels = jsonData[region.value][town.value];
cmo(hotels, hotel);
};
function cmo(arr, s){
arr.forEach(o => {
let opt = document.createElement("option");
opt.value = o;
opt.innerHTML = o;
s.add(opt);
});
}
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="./styles.css">
<title>Generowanie - wybór danych</title>
</head>
<body>
<p><label for = "region">Choose a region:</label>
<select name = "region" id = "region" onchange="setTown();">
<option disabled selected value="">Select a region</option>
<option value = "Warmińsko - mazurskie">Warmińsko - mazurskie</option>
<option value = "Małopolskie">Małopolskie</option>
<option value = "Podlaskie">Podlaskie</option>
<option value = "Podkarpackie">Podkarpackie</option>
<option value = "Mazowieckie">Mazowieckie</option>
</select>
</p>
<p>
<label  for = "town">Choose a town:</label>
<select name = "town" id="town" onchange="setHotel();">
</select>
</p>
<p>
<label for="hotel" id="hotel">Choose a hotel:</label>
<select name="hotel" id="hotel">
</select>
</p>
<script type="text/javascript" src="./scripts.js"></script>
</body>
</html>

我将从这个开始,即使它与您的问题无关:

var jsonData = JSON.parse(JSON.stringify(json));

这是不必要的。变量json是一个对象,而不是实际的 JSON。 此行将其转换为 JSON(带stringify),然后转换回与您开始使用的对象(带parse)相同的对象。 您可以跳过所有这些,直接使用json(最好使用较少误导性的名称)。

现在回答您的问题:

这里有很多问题,其中大多数归结为"你正在将 null 传递给它期望数组cmo":

  • 您尝试在加载时运行函数,当未选择任何内容时,这会将 null 传递给cmo
  • 清空城镇<select>也会触发其 onChange 事件,将其 null 值传递给setHotel,然后cmo
  • 数据
  • 中有名为"region"和"town"的额外键,在尝试与该数据匹配时,您没有考虑这些键
  • 您的 HTML 中有一个重复的 ID,因此当您尝试检查酒店选择的值时,您反而获得了其label的(不存在的)值
  • 。并且您的数据中有您意外尝试作为数组访问的对象。

以下是更正后的版本;我在对您的代码进行更改的地方添加了注释:

// renamed this, and removed the unneeded stringify-and-parse dance
var jsonData = {
"region": {
"Warmińsko - mazurskie": {
"town": {
"Olsztyn": ["Mercury", "Novotel", "Sheraton", "Radisson", "Gołębiewski"],
"Elbląg": ["Mercury", "Novotel", "Sheraton", "Radisson Blue", "Gołębiewski"],
"Iława": ["Mer", "Novotel", "Sheraton", "Radisson", "Gołębiewski"],
"Ostróda": ["Mercury", "Novotel", "Mariot", "Radisson", "Gołębiewski"],
"Giżycko": ["Mercury", "Novotel", "Sheraton", "Vienna House", "Gołębiewski"],
}
},
"Małopolskie": {
"town": {
"Kraków": ["Kossak", "Novotel", "Sheraton", "Radisson", "Stary"],
"Tarnów": ["Mercury", "Novotel", "Sheraton", "Tarnovia", "Ibis"],
"Oświęcim": ["Mercure", "Golden Tulip", "Sheraton", "Radisson", "Hampton"],
"Skała": ["Focus", "Novotel", "Sheraton", "Radisson", "Zamek"],
"Wieliczka": ["Mercurius", "Novotel", "Sheraton", "Arche", "Blue Star"],
}
},
"Podlaskie": {
"town": {
"Białystok": ["Altus", "Deo", "Sheraton", "Radisson Blu", "Aquarion"],
"Suwałki": ["Merr", "Novotel", "Ibis", "Radisson Red", "Arche"],
"Łomża": ["Mercury 2", "Telios", "Sheraton", "Blue", "DeSilva"],
"Augustów": ["Mariot", "Unicus", "Hampton", "Ibis Budget", "Ibis Styles"],
"Zambrów": ["Golden", "Blue Star", "Sheraton", "Osteria", "Rafles"],
}
},
"Podkarpackie": {
"town": {
"Rzeszów": ["Blue Star", "Notel", "Radius", "Puławski", "Grębiewski"],
"Jasło": ["Mercury2", "Novotel2", "Sheraton2", "Radisson2", "Gołębiewski2"],
"Krosno": ["Mercury3", "Novotel3", "Sheraton3", "Radisson3", "Gołębiewski3"],
"Ustrzyki Górne": ["Mercury4", "Novotel4", "Sheraton4", "Radisson4", "Gołębiewski"],
"Sanok": ["Mercury5", "Novotel5", "Sheraton5", "Radisson5", "Gołębiewski5"],
}
},
"Mazowieckie": {
"town": {
"Warszawa": ["Mercury6", "Novotel6", "Sheraton6", "Radisson6", "Gołębiewski6"],
"Sochaczew": ["Mercury7", "Novotel7", "Sheraton7", "Radisson7", "Gołębiewski7"],
"Płock": ["Mercury8", "Novotel8", "Sheraton8", "Radisson8", "Gołębiewski8"],
"Radom": ["Mercury9", "Novotel9", "Sheraton9", "Radisson9", "Gołębiewski9"],
"Ciechanów": ["Mercury0", "Novotel0", "Sheraton0", "Radisson0", "Gołębiewski0"],
}
}
}
}
var region = document.getElementById("region");
var town = document.getElementById("town");
var hotel = document.getElementById("hotel");
// removed attempts to init while selects are all empty
function setTown() {
town.innerHTML = "";
// corrected this line:
let towns = Object.keys(jsonData.region[region.value].town);
cmo(towns, town);
setHotel();
};
function setHotel() {
hotel.innerHTML = "";
// corrected this line:
let hotels = jsonData.region[region.value].town[town.value];
cmo(hotels, hotel);
};
function cmo(arr, s) {
if (arr.length) { // added this for safety: check if it's an array before you try to iterate over it
arr.forEach(o => {
let opt = document.createElement("option");
opt.value = o;
opt.innerHTML = o;
s.add(opt);
});
}
}
<p><label for="region">Choose a region:</label>
<select name="region" id="region" onchange="setTown();">
<option disabled selected value="">Select a region</option>
<option value="Warmińsko - mazurskie">Warmińsko - mazurskie</option>
<option value="Małopolskie">Małopolskie</option>
<option value="Podlaskie">Podlaskie</option>
<option value="Podkarpackie">Podkarpackie</option>
<option value="Mazowieckie">Mazowieckie</option>
</select>
</p>
<p>
<label for="town">Choose a town:</label>
<select name="town" id="town" onchange="setHotel();">
</select>
</p>
<p>
<!-- changed this ID to not be a duplicate: -->
<label for="hotel" id="hotelLabel">Choose a hotel:</label>
<select name="hotel" id="hotel">
</select>
</p>

最新更新