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
.