Всем привет. Изучаю JavaScript, читаю учебник "Выразительный JavaScript" и дошел до интересной задачи в конце пятой главы.
Задание выглядит так:
В качестве призовой игры напишите функцию groupBy, абстрагирующую операцию группировки. Она должна принимать массив и функцию, которая вычисляет группу для элементов массива, и возвращать объект, который сопоставляет названия групп массивам членов этих групп.
Я решил что буду писать прототипированный метод для массивов, чтобы в функцию массив передавался как массив.метод()
В общем вот код, он работает прекрасно, всё как нужно отрабатывает. Принёс Вам его на суд, что Вы скажете? Есть какие-то явные огрехи и говнокод?
Array.prototype.groupBy = function(acto) {
var tempObj = {}; //Создаем пустой объект
for (var i=0; i<this.length; i++){ //Запускаем проход по массиву
var temp = acto(this[i]); //Создаём переменную, куда помещаем результат вызова функции переданной аргументом. Условимся о том, что функция, передаваемая аргументом, должна возвращать строку
if (!tempObj[temp]) { //Проверяем наш объект и если в нём нет свойства с таким именем, то
tempObj[temp] = [this[i]]; //Создаём свойство с таким именем куда помещаем массив, в который, в свою очередь, помещаем элемент итерации
} else { //Иначе
tempObj[temp].push(this[i]); //в массив-свойство объекта добавляем результат операции
}
}
return tempObj; //Возвращаем объект
}
Пример работы:
Array.prototype.groupBy = function(acto) {
var tempObj = {}; //Создаем пустой объект
for (var i = 0; i < this.length; i++) { //Запускаем проход по массиву
var temp = acto(this[i]); //Создаём переменную, куда помещаем результат вызова функции переданной аргументом. Условимся о том, что функция, передаваемая аргументом, должна возвращать строку
if (!tempObj[temp]) { //Проверяем наш объект и если в нём нет свойства с таким именем, то
tempObj[temp] = [this[i]]; //Создаём свойство с таким именем куда помещаем массив, в который, в свою очередь, помещаем элемент итерации
} else { //Иначе
tempObj[temp].push(this[i]); //в массив-свойство объекта добавляем результат операции
}
}
return tempObj; //Возвращаем объект
}
var arrayWithTrash = [1, 2, 3, "A", "B", "C", 4, 5, 6, true, [1, 2, 3], {
"a": 250
}];
console.log(
arrayWithTrash.groupBy(function(elemArray) {
if (typeof elemArray === "number") return "Number";
else if (typeof elemArray === "string") return "String";
else if (typeof elemArray === "boolean") return "Boolean";
else return "Other";
})
);
.as-console-wrapper {
min-height: 100% !important;
top: 0;
}
Во-первых, добавлять перечисляемое свойство в массив - ужасная идея! Как минимум, его следует сделать неперечисляемым. Для этого можно использовать Object.defineProperty:
Object.defineProperty(Array.prototype, "groupBy", {
value: function (acto) {
// ...
},
});
Во-вторых, лучше давать переменным понятные названия. Не acto
, temp
, tempObj
- а keySelector
, key
, result
.
В-третьих, у вас будут баги с такими ключами, как toString
. Чтобы создаваемый пустой объект был реально пустым - надо использовать не {}
, а Object.create(null)
.
В-четвертых, большинство методов массива передают в callback вторым аргументом индекс элемента в массиве, а третьим - сам массив. Возможно, вам стоит ради красоты сделать так же - это же ничего не стоит.
Забавная задачка.
Но простая, поэтому код тоже простой, оптимизировать нечего особо (разве что добавить проверок на входные данные).
Изменять/добавлять прототипы встроенных объектов - плохо, не делайте этого.
const groupBy = (a, fn, full = {}) => a.forEach((e, _) => (_ = fn(e) + '') && (full.hasOwnProperty(_) ? full[_].push(e) : full[_] = [e])) || full;
var arrayWithTrash = [1, 2, 3, "A", "B", "C", 4, 5, 6, true, [1, 2, 3], {a: 250}],
fn = function(elemArray) {
if (typeof elemArray === "number") return "Number";
else if (typeof elemArray === "string") return "String";
else if (typeof elemArray === "boolean") return "Boolean";
else return "Other";
};
console.info(groupBy(arrayWithTrash, fn));
.as-console-wrapper {
min-height: 100% !important;
top: 0;
}
Всю служебную информацию записывать в консоль (старт прогресса / старт анимации ячейки / окончание анимации ячейки / окончание прогресса)
Есть блок div, в него вложена ссылка На блоке висит функция, которая возращает return false по клику на этот блок
Друзья, помогите разобраться пожалуйста! Пытаюсь разобраться с jquery, задача следующая: при выборе марки машины из селекта, в соседнем div появляется...