Задачи по 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, время: 17:21. |