Задачи по js
Здравствуйте, друзья.
Прошу проверить, выполненные мной задачи по js Первые две задачи очень похожи и я попробовал написать для них решения чуть по-разному Если оба решения правильны, то подскажите какое из них более грамотное? Так же буду признателен за примеры оптимальных решений для всех задач Задача #1 Условие Написать функцию `isAllTrue`, которая принимает 2 параметра: `source` и `filterFn`, где `source` - массив, `filterFn` - фильтрующая функция Если фильтрующая функция вернет `true` для ВСЕХ элементов массива, то и сама `isAllTrue` вернет `true` Если фильтрующая функция вернет `false` хотя бы для одного элемента массива, то и сама `isAllTrue` вернет `false` Выбрасывать и обрабатывать исключение, если в 'source' пустой массив Пример var allNumbers = [1, 2, 4, 5, 6, 7, 8], someNumbers = [1, 2, 'привет', 4, 5, 'мир', 6, 7, 8], noNumbers = ['это', 'массив', 'без', 'чисел']; function isNumber(val) { return typeof val === 'number'; } console.log(isAllTrue(allNumbers, isNumber)); //вернет true console.log(isAllTrue(someNumbers, isNumber)); //вернет false console.log(isAllTrue(noNumbers, isNumber)); //вернет false Решение let source1 = [1,2,3], source2 = ['text',2], source3 = [1,'text'], source4 = [1,'text',3], source5 = ['text1','text2'], source6 = []; function isAllTrue(src, fltr) { if (src.length == 0) { throw new Error('Массив пустой'); } let result = true; for (let i = 0; i < src.length; i++) { if (fltr(src[i]) != true) { result = false; } } return result; } function filterFn(arg) { return typeof arg === 'number'; } try { let res = isAllTrue(source6, filterFn); console.log('%s %s', 'Задача №1: ', res); } catch(e) { console.error('%s %s', 'Задача №1: ', e.message); } Задача #2 Условие Написать функцию 'isSomeTrue', которая принимает 2 параметра - 'source' и 'filterFn', где 'source' - массив, 'filterFn' - фильтрующая функция Если фильтрующая функция вернет 'false' для ВСЕХ элементов массива, то и сама 'isSomeTrue' вернет 'false' Если фильтрующая функция вернет 'true' хотя бы для одного элемента массива, то и сама 'isSomeTrue' вернет 'true' Всё должно быть реализовано с использованием чистого js (не используя сторонние библиотеки) Так же, нельзя использовать функции для работы с массивами Решение let source1 = [1,2,3], source2 = ['text',2], source3 = [1,'text'], source4 = [1,'text',3], source5 = ['text1','text2']; function isAllTrue(src, fltr) { let result; for (let i = 0; i < src.length; i++) { if (fltr(src[i]) == true) { result = true; return result; } else { result = false; } } return result; } function filterFn(arg) { return typeof arg === 'number'; } let res = isAllTrue(source5, filterFn); console.log('%s %s', 'Задача №2: ', res); Задача №3 Условие Написать функцию 'calculator' (в виде модуля), которая имеет один параметр - 'firstNumber', где 'firstNumber' - это число, с которым будут производиться действия Функция 'calculator' должна возвращать объект, у которого должно быть несколько функций
Предусмотреть исключительные ситуации, для функции 'div', когда делитель равен нулю Пример let myCalculator = calculator(100); console.log(myCalculator.sum(1, 2, 3)); //вернет 106 console.log(myCalculator.dif(10, 20)); //вернет 70 console.log(myCalculator.div(2, 2)); //вернет 25 console.log(myCalculator.mul(2, 2)); //вернет 400 Решение Файл calculator.js let calc = function calculator(firstNumber) { let result = firstNumber; let obj = { sum: function() { for(let i = 0; i < arguments.length; i++) { result += arguments[i]; } return result; }, dif: function() { for(let i = 0; i < arguments.length; i++) { console.log(result); result -= arguments[i]; } return result; }, div: function() { for(let i = 0; i < arguments.length; i++) { if (arguments[i] == 0) { throw new Error('Делитель равен нулю'); } else { result /= arguments[i]; } } return result; }, mul: function() { for(let i = 0; i < arguments.length; i++) { result *= arguments[i]; } return result; }, } return obj; } module.exports = calc; Файл script.js let calcFn = require('./calculator.js'); let myCalc = calcFn(8); console.log('%s %s', 'Задача №3: ', myCalc.sum(3, 2, 0)); console.log('%s %s', 'Задача №3: ', myCalc.dif(3, 2, 0)); try { console.log('%s %s', 'Задача №3: ', myCalc.div(3, 2, 0)); } catch(e) { console.error('%s %s', 'Задача №3: ', e.message); } console.log('%s %s', 'Задача №3: ', myCalc.mul(3, 2, 0)); |
Ну на вскидку всё верно, разве что в первой задаче после result = false, следует сделать break из цикла, ибо одного false достаточно. Во второй же задаче, аналогично, else лишний: нет никакого смысла каждую итерацию переопределять result как false, т.к. первый же true приведёт к завершению функции, имеет смысл присвоить result = false в самом начале по аналогии с первой функциией.
Ставить в циклах break, а return делать в конце, или делать return сразу в цикле - вопрос исключительно стиля кода, т.е. делайте так, как вам преподают. То же касательно if(foo == true) vs if(foo) и if(bar != true), if(bar == false) vs if(!bar), первое нагляднее и считается более правильным, но второе проще и встретить можно чаще. По последней функции: поскольку вы используете let, то, надо полагать, подразумевается самый современный javascript, тогда можно было бы сделать всё по-модному, например: dif: function() { for(let i = 0; i < arguments.length; i++) { console.log(result); result -= arguments[i]; } return result; },-> dif: (...args) => args.reduce( (a, b) => a - b, result ),Но это если только вам показывали такую "магию". Сам по себе ваш вариант ничуть не хуже, и скорее всего даже производительнее.) Единственный момент, в последней функции у вас переменная result для всех методов едина, а значит все вычисления для конкретного myCalculator сохраняются, что было бы логично, но судя по примеру каждый раз вычисления должны начинаться с изначального значения. |
Ну и разумным шагом было бы превратить Calculator в конструктор:
function Calculator(firstNumber) { if(!(this instanceof Calculator)) return new Calculator(firstNumber); this.firstNumber = firstNumber; } Calculator.prototype = { sum: function() { let result = this.firstNumber; for(let i = 0; i < arguments.length; i++) { result += arguments[i]; } return result; }, dif: function() { let result = this.firstNumber; for(let i = 0; i < arguments.length; i++) { result -= arguments[i]; } return result; }, div: function() { let result = this.firstNumber; for(let i = 0; i < arguments.length; i++) { if (arguments[i] == 0) { throw new Error('Делитель равен нулю'); } else { result /= arguments[i]; } } return result; }, mul: function() { let result = this.firstNumber; for(let i = 0; i < arguments.length; i++) { result *= arguments[i]; } return result; }, } module.exports = Calculator;Разница с вашим вариантом(кроме исправления result) в том, что для каждого новосозданного объекта будут использованы одни и те же функции, без копирования, тогда как у вас каждый раз они создаются заново. Но, опять же, использовать это имеет смысл, если вы проходили что такое прототипы.) P.S. На счёт оптимальных первых двух задач - вопрос тонкий, ибо в современном js существуют нативные some и every.:) |
А ты попробуй через рекурсию
|
Рекурсия тут не пришей к п... не нужна, в общем, совсем.
|
Большое спасибо, советы взял на заметку.
Есть еще задачка, которую я тоже вроде как решил, но сомневаюсь насчет оптимальности решения. Задача #4 Условие Напишите модуль, который экспортирует функцию с именем `consoleRec` Функция должна рекурсивно выводить элементы массива на экран Запрещено использовать циклы и методы для работы с массивами Функция должна принимать два аргумента: массив и что-то еще на ваше усмотрение Пример consoleRec(['я', 'умею', 'писать', 'рекурсивные', 'функции']); Должна вывести на экран: я умею писать рекурсивные функции Решение Файл script.js let recurtion = require('./recurtion.js'), array = ['я', 'умею', 'писать', 'рекурсивные', 'функции'], myName = 'spo'; recurtion(array, myName); Файл recurtion.js let i = 0; module.exports = function consoleRec(arr, name) { if(i < arr.length) { if(i == 0) { console.log(arr[i] + ' - ' + name); } else { console.log(arr[i]); } i++; consoleRec(arr, name); } } Вопрос Про module.exports пока знаю мало и не понимаю почему, экспортируя только функцию, я имею доступ и к переменной i? |
Нет, оно конечно сработает. Но только один раз, ибо при следующем вызове i будет равно длине массива из предыдущего вызова, а не нулю. Т.к. функция импортируется единожды, единожды импортируется и "верхняя" i, которую функция свободно изменяет.
Решений данной задачи множество, и самый простой вариант - передавать i дополнительным параметром. По поводу это самой i. Важнейшая для понимания javascript как такового информация. |
Возможно именно на это намекает условие, когда говорит про второй параметр. А я не так понял и передал произвольный ) Спасибо.
|
Я думаю, что второй параметр используется именно для этого:
let consoleRec = (source, iter) => { if (source[iter] !== undefined) { console.log(source[iter++]); consoleRec(source, iter); } } module.exports = { 'consoleRec': consoleRec }; А использовать можно так: let tools = require('./tools.js'); tools.consoleRec(['я', 'умею', 'писать', 'рекурсивные', 'функции'], 0); |
Часовой пояс GMT +3, время: 08:42. |