Итак, прямо сейчас я разрабатываю систему, в которой учащиеся могут ставить свои отметки в форму, которая будет запускать функцию, которая помещает все отметки в массив как объект.
Нравится: {english_period1: 10, english_period2: 7} <Пример
Но если я хочу запустить array.prototype.forEach, чтобы что-то сделать с метками внутри массива. Он абсолютно ничего не возвращает. .ForEach даже не запустится.
Это сценарий:
// Make new variable which will store the marks
let allMarks = [];
document.querySelector("#marks").addEventListener('submit', e => {
e.preventDefault();
//Execute for each input
for(let i = 0; i < e.srcElement.length-1; i++){
// Assign name and value
const name = e.srcElement[i].name;
const value = e.srcElement[i].value;
//Check if value is a mark (number)
if (value % 1 == 0 && value <= 10){
//Assign mark
allMarks[name] = value;
}else{
//Value is not a mark, check if it's a O, V or G
if (value == "O" || value == "V" || value == "G"){
allMarks[name] = value;
}else{
console.info("Niet toegestaan");
}
}
}
allMarks.forEach(mark => {
console.info("hello world");
});
},false);
Что он делает:
Цель сценария - вычислить средние оценки учащихся и проверить их на соответствие некоторым правилам, чтобы узнать, прошли ли они учебный год.
Что я делаю неправильно? Разве нельзя использовать array.prototype.forEach над массивом, содержащим объекты? Как мне оптимизировать этот фрагмент кода?
Заранее спасибо!
Вместо использования: allMarks[name] = value, который не будет добавлять элемент в массив allMarks = []. Использование allMarks.push({name: name, value: value}); поможет. Потому что теперь он добавит элемент в массив (объект), и, таким образом, forEach может перебирать каждый элемент и получать его значения, как обычный объект.
Особая благодарность: @mhodges
Итак, после отладки и написания большего количества скрипта я пришел к выводу, что использование объекта, как некоторые из предложенных в ответах ниже, является лучшим и красивым вариантом.
Можно динамически добавлять ключи к объекту с помощью objectName[variableName]. С помощью Object.keys(objectName) вы можете перебрасывать ключи в массив и перебирать ключи. Это приведет (в моем случае) к более красивой структуре данных:
Вместо: [{field: "English", period: "period_1", mark: "7.5"}]
Это вернет:
"English": {
"period_1": 7.5,
"period_2": 6.4
}
Примечание: allMarks будет массивом строк, а не массивом объектов.
Другое примечание: этот код работает, но не так, как хотелось бы. Это: allMarks[name] = value создаст / перезапишет свойство объекта с ключом, равным значению содержимого переменной name, и значением, равным значению переменной value. Это свойство объекта будет помещено в объект-массив с именем allMarks, но не добавляет элемент массива. Это легко проверить: console.info(allMarks[name]); как последняя строка в цикле for().
Спасибо @mhodges! Оно работает! Вместо того, чтобы делать allMarks[name] = value;, который делает что-то, чего я до сих пор не понимаю. Делаю allMarks.push({name: name, value: value}); работает. Потому что теперь я могу перебирать каждый элемент в массиве и получать его имя и значение. Именно то, что я хочу, но я бы предпочел объект, чтобы я мог набрать: например, english_period1.value. Не мог понять, так что это был для меня более понятный вариант. Спасибо еще раз!



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Обратите внимание, что немного сложно сказать, что именно вы здесь пытаетесь сделать. Если вы используете необходимостьallMarks как массив, вам нужно добавить каждый отдельный mark в массив allMarks, как показано ниже:
// Make new variable which will store the marks
let allMarks = [];
document.querySelector("#marks").addEventListener('submit', e => {
e.preventDefault();
//Execute for each input
for(let i = 0; i < e.srcElement.length-1; i++){
// Assign name and value
const name = e.srcElement[i].name;
const value = e.srcElement[i].value;
// <-- create new mark object -->
const newMark = {name: value}
//Check if value is a mark (number)
if (value % 1 == 0 && value <= 10){
//Assign mark
//<-- instead of allMarks[name] = value; -->
//<-- you need to add the newMark to the allMarks array -->
allMarks.push(newMark);
}else{
//Value is not a mark, check if it's a O, V or G
if (value == "O" || value == "V" || value == "G"){
//<-- same thing here -->
allMarks.push(newMark);
}else{
console.info("Niet toegestaan");
}
}
}
allMarks.forEach(mark => {
console.info("hello world");
});
},false);
Однако вместо этого вы можете сделать allMarks объектом, а затем установить каждый отдельный mark в качестве пары ключ-значение для этого объекта. Вы по-прежнему сможете перебирать пары ключ, значение в объекте, но не сможете использовать .forEach.
Что бы вы предпочли?
Я думаю, что будет проще, если вы создадите как объект, а не как массив.
например.
var allMarks = {};
и внутри вы можете использовать
var marks;
marks.name = name;
marks.value = value;
allMarks.push(marks);
тогда вы можете использовать
allMarks.forEach(function(mark){
console.info(mark.name);
console.info(mark.value);
});
.forEach не является свойством по умолчанию для объектов JS.
Как и .push()
Это была моя первоначальная проблема с использованием объекта, оба не используются по умолчанию для объектов. И, таким образом, сложнее обезопасить все входы (а их много, ха-ха).
Ваш allMarks[name] = value превращает массив allMarks в массив с буквальными свойствами (с поведением объекта), .forEach() не будет запускаться с этим. Вы можете использовать allMarks как объект:
let allMarksKeys = Object.keys(allMarks);
allMarksKeys.forEach(key => // for example use allmarks[key] to access object elements)
и т.п.
forEach будет работать с массивами, но индекс массива должен быть числовым (целочисленное значение).
Я не думаю, что
allMarks[name] = valueделает то, что вы думаете. Вы устанавливаете свойства в массиве, а не заполняете массив значениями - поэтому.forEach()не выполняет итерацию - в массиве нет элементов. Попробуйте вместо этого использоватьallMarks.push(value)и посмотрите, сработает ли это для вас.