https://codepen.io/Alfa_main/pen/gJyQeN
Здравствуйте хочу попросить у вас помощи) Есть задача: Дано колличество каллорий маленького и большого гамбургера + добавки к ним, при выборе одного из гамбургеров и добавки к нему подсчитывается цена и калории обоих) Я сделал задание в лоб(совсем нехорошим способом) , каким еще способом можно решить данную задачу, более профессионально) Ссылка на codepen выше, заранее благодарен за помощь)
Способ нехороший потому что код сложно расширять. В код как-бы зашито знание о том какие бывают топпинги и какие бургеры. Обычно стратегия такая чтобы описать с помощью структур данных (массивов и объектов), и описать код в общем виде. Трюк которого я не вижу в коде, но который поможет написать код в общем виде, состоит в том чтобы использовать переменную с именем свойства объекта для доступа к значению свойства. Пример механики
const propName = 'userName'
const obj = {
userName: 'dima',
gender: 'male'
}
console.log(obj[propName]) // 'dima'
Далее по коду. Примерно такие структуры данных описывают достаточно хорошо ситуацию:
const burgers = {
small: {
price: 1,
ccal: 10
},
large: {
price: 2,
ccal: 15
}
}
const toppings = {
salad: {
price: 1,
calories: 10
},
cheese: {
price: 2,
calories: 50
},
ham: {
price: 5,
calories: 40
}
]
Далее нужно в html/js описать код так чтобы можно было получить при клике, строки small или large записывались в переменную burgerType.
Описать код, чтобы получить массив топпингов в виде ['cheese', 'ham'] в переменную selectedToppings
Тогда вычисление итоговых значений будет иметь достаточно общий вид:
const burgerPrice = burgers[burgerType].price
let toppingsPrice = 0
for (let i = 0; i < selectedToppings.length; i += 1) {
const selectedToppingName = selectedToppings[i]
toppingsPrice = toppingsPrice + toppings[selectedToppingName].price
}
const totalPrice = burgerPrice + toppingsPrice
Хороший способ но немного непонятно как это реализовать, я новичок и пока что не пойму как внедрить данный способ)
Ну смотри, давай попробуем начать отбрасывать лишнее:
у тебя есть объект burgers и объект stuffing, которые, по сути, описывают одно и то же: какой-то продукт, его цену, и калорийность. Но при этом структура данных у них вообще разная. И все поля называются по-разному:
// stuffing
cheese:{
priceCheese : 4,
ccalCheese : 25,
},
salad:{
priceSalad : 5,
ccalSalad : 5,
},
// burgers:
price:{
priceSmallGamburger : 17,
priceBigGamburger : 25,
},
ccal:{
ccalSmallGamburger : 250,
ccalBigGamburger : 350,
},
как эти структуры можно упростить и сделать более одинаковыми?
https://codepen.io/Alfa_main/pen/gNYvyg вот пробую но всеравно до конца не понятно как значение попадет в функцию
В самом начале onclick функции ты объявляешь пачку переменных (burgerType и прочие). Посмотри внимательно, что в них попадает, и как ты потом их используешь.
Ну вначале я объявляю константу инпутов бургеров, потом добавок к ним для того, чтобы считать выбранный инпут и применить к нему функцию, но тут нет checked у меня нигде, где то портачу и не могу найти пока что где) price is not defined, догадываюсь что это связанно с неправильным указанием DOM, не туда засовываю радиоинпуты) Возможно в selectedToppings и burgerType нужно добавить названия ключей в виде массива, но как тогда возможно считать значение инпута который отметил пользователь
Ну ок, смотри,
let burgerType = document.querySelectorAll('.radio__gamburger');
const burgerPrice = burgers[burgerType].price;
какой тип данных у burgerType?
А какой должен быть, чтобы burgers[burgerType] корректно отработал?
Думаю тип object https://codepen.io/Alfa_main/pen/jjOzGK типо этого но ошибка не уходит, массив попадает в переменную, и одно из его значений должно применяться к burgerPrice, но не попадает
Хорошо, давай смотреть:
const burgers = {
small:{
price : 17,
ccal : 250,
},
large:{
price : 25,
ccal : 350,
}
};
const burgerType = ['small','large'];
const burgerPrice = burgers[burgerType].price;
Ты передаешь в burgers ключом весь массив burgerType. Пытаясь достать из объекта значение, он превращает его в строку (потому что ключи объектов всегда - строки) 'small, large'. Потому что если ты вызовешь burgerType.toString(), то как раз эту строку и получишь.
В результате объект burgers, в котором два ключа small и large, пытается найти данные с ключом 'small, large', которых там нет. Поэтому burgers[burgerType] превращается в undefined и вот это выражение
const burgerPrice = burgers[burgerType].price;
превращается в undefined.price и падает с ошибкой Cannot read property 'price' of undefined.
То же самое и в прошлом примере:
let burgerType = document.querySelectorAll('.radio__gamburger');
const burgerPrice = burgers[burgerType].price;
burgerType.toString() получит на выходе какой-нибудь [object Nodelist], а такого ключа в объекте burgerPrice нет.
Да, ты выгреб два ДОМ-элемента .radio_gamburger, но ты не можешь пихать их напрямую в объект burgerPrice.
Тебе нужно:
- Выбрать из двух найденных ДОМ-элементов один, тот, который пользователь чекнул.
- Каким-то образом проассоциировать этот дом-элемент со строкой (
smallилиlarge, потому что именно такие ключи есть в объектеburgers), которую ты потом передашь в объектburgers.