/*makeProfileTimer Напишите функцию makeProfileTimer, которая служит для замера времени выполнения другого кода и работает следующим образом:*/ /*var timer = makeProfileTimer() alert('Замеряем время работы этого alert'); //некий код, время выполнения которого мы хотим измерить с высокой точностью alert(timer()); //alert должен вывести время в микросекундах от выполнения makeProfileTimer до момента вызова timer(), // т. е. измерить время выполнения alert //Используйте performance.now() */ function makeProfileTimer() { const t0 = performance.now() return () => { const t1 = performance.now() return t1 - t0 } } var timer = makeProfileTimer() alert('Замеряем время работы этого alert') alert(timer()) /*makeSaver Напишите функцию makeSaver, которая:*/ { function makeSaver (f) { const fResult = f() function result(){ return fResult } return result } var saver = makeSaver(Math.random) //создает функцию-хранилище результата переданной в качестве параметра функции (Math.random // в примере). На этом этапе Math.random НЕ вызывается var value1 = saver() //saver вызывает переданную в makeSaver функцию, запоминает результат и возвращает его var value2 = saver() //saver в дальнейшем просто хранит результат функции, и более НЕ вызывает переданную //в makeSaver функцию; value1 === value2 // всегда true var saver2 = makeSaver(() => console.log('saved function called') || [null, undefined, false, '', 0, Math.random()][Math.ceil(Math.random()*6)]) var value3 = saver2() var value4 = saver2() value3 === value4 // тоже должно быть true let namePrompt = prompt.bind(window, 'Как тебя зовут?') let nameSaver = makeSaver(namePrompt) alert(`Привет! Prompt еще не было!`) alert(`Привет ${nameSaver()}. Только что запустился prompt, первый и последний раз`) alert(`Слушай, ${nameSaver()}, го пить пиво. Ведь prompt был только один раз`) } /* Таким образом makeSaver решает две задачи: Навсегда сохраняет результат функции. Это актуально, например, для Math.random. Действует лениво, то есть вызывает Math.random только тогда, когда результат действительно нужен. Если же по каким-то причинам значение не понадобится, то Math.random даже не будет вызван*/ /*myBind Изучите встроенную функцию bind, и сделайте свою версию, которая позволит определить "значение по умолчанию" не только для первых параметров, но для любых других, например для степени в Math.pow: var pow5 = myBind(Math.pow, Math, [, 5]) // первый параметр - функция для биндинга значений по умолчанию, // второй - this для этой функции, третий - массив, в котором undefined означает // параметры, которые должны передаваться при вызове, // а другие значения являются значениями по умолчанию: var cube = myBind(Math.pow, Math, [, 3]) // cube возводит число в куб pow5(2) // => 32, вызывает Math.pow(2,5), соотнесите с [undefined, 5] cube(3) // => 27 var chessMin = myBind(Math.min, Math, [, 4, , 5,, 8,, 9]) chessMin(-1,-5,3,15) // вызывает Math.min(-1, 4, -5, 5, 3, 8, 15, 9), результат -5 var zeroPrompt = myBind(prompt, window, [undefined, "0"]) // аналогично, только теперь задается "0" как текст по умолчанию в prompt, // а текст приглашения пользователя задается при вызове zeroPrompt var someNumber = zeroPrompt("Введите число") // вызывает prompt("Введите число","0") const bindedJoiner = myBind((...params) => params.join(''), null, [, 'b', , , 'e', 'f'])//('a','c','d') === 'abcdef' bindedJoiner('a','c','d') === 'abcdef' bindedJoiner('1','2','3') === '1b23ef' Массив, который идет третьим параметром определяет, какие поля должны подменяться значением по умолчанию, а какие - задаваться в последствии (undefined).*/ { function sum(a, b, c, d) { return a + b + c + d } function myBind(func, context, args) { return function funcResult(...lostArgs) { let combinedArgs = [] for (let i of args) { if (i === undefined) { combinedArgs.push(lostArgs[0]) lostArgs.shift() } else { combinedArgs.push(i) } } return func.apply(context, combinedArgs) } } const resultBind = myBind(sum, null, [, 2, , 2]) console.log(resultBind(2, 2)) var pow5 = myBind(Math.pow, Math, [, 5]) // первый параметр - функция для биндинга значений по умолчанию, // второй - this для этой функции, третий - массив, в котором undefined означает // параметры, которые должны передаваться при вызове, // а другие значения являются значениями по умолчанию: var cube = myBind(Math.pow, Math, [, 3]) // cube возводит число в куб console.log(pow5(2)) // => 32, вызывает Math.pow(2,5), соотнесите с [undefined, 5] console.log(cube(3)) // => 27 var chessMin = myBind(Math.min, Math, [, 4, , 5,, 8,, 9]) console.log(chessMin(-1,-5,3,15)) // вызывает Math.min(-1, 4, -5, 5, 3, 8, 15, 9), результат -5 var zeroPrompt = myBind(prompt, window, [undefined, "0"]) // аналогично, только теперь задается "0" как текст по умолчанию в prompt, // а текст приглашения пользователя задается при вызове zeroPrompt var someNumber = zeroPrompt("Введите число") // вызывает prompt("Введите число","0") const bindedJoiner = myBind((...params) => params.join(''), null, [, 'b', , , 'e', 'f'])//('a','c','d') === 'abcdef' console.log(bindedJoiner('a','c','d') === 'abcdef') console.log(bindedJoiner('1','2','3') === '1b23ef') /* checkResult Напишите декоратор checkResult, который: принимает функцию для запуска и проверки результата (оригинал) принимает функцию для проверки результата (валидатор) возвращает обертку, которая запускает оригинал до тех пор, пока оригинал не вернет значение, удовлетворяющее функции-валидатору. В валидатор передается результат оригинальной функции. Если валидатор возвращает true, то обертка возвращает результат оригинальной функции. Если валидатор возвращает что-то другое, то оригинал запускается еще, пока валидатор не вернет true.*/ function checkResult(original, validator){ function wrapper(...params){ let result = original(...params) if (!validator(result)) { return wrapper(...params) } return result } return wrapper } //numberPrompt - это функция, которая будет запускать prompt до тех пор, пока пользователь не введет число const numberPrompt = checkResult(prompt, x => !isNaN(+x)) let number = +numberPrompt("Введите число", "0") //параметры передаются насквозь в оригинал. Не забудьте передать this, используя call или apply //gamePrompt - это функция, которая будет запускать prompt до тех пор, пока пользователь не введет одно из слов 'камень', 'ножницы', 'бумага' const gamePrompt = checkResult(prompt, x => ['камень', 'ножницы', 'бумага'].includes(x.toLowerCase())) const turn = gamePrompt("Введите что то из списка: 'камень', 'ножницы', 'бумага'") /* Используя checkResult сделайте функции, которые: randomHigh. Возвращает случайное число в диапазоне от 0.5 до 1*/ const randomHigh = checkResult(Math.random, x => x >= 0.5 && x <=1 ? true : false ) //alwaysSayYes. Достает пользователя окном confirm пока он не согласится (не нажмет OK) const alwaysSayYes = checkResult(confirm, x => x) //respectMe. Достает пользователя запуском этой фунцкии, пока какое-то из полей не введено*/ const respectMe = checkResult(person, validatorCredentials) function person() { let trimAndCapitalize = (str) => { if (str) { return str.trim()[0].toUpperCase() + str.trim().slice(1).toLowerCase() } } let surname = trimAndCapitalize( prompt('введите вашу фамилию.\nMожете добавить пару пробелов в конце или начале. Написать с маленькой буквы или даже сделать пару букв в середине фамилии большими, я все поправлю!') ); let name = trimAndCapitalize( prompt('введите ваше имя') ); let fatherName = trimAndCapitalize( prompt('введите ваше отчество') ); let fullName = surname + " " + name + " " + fatherName; return { name, surname, fatherName, fullName } } function validatorCredentials({ name, surname, fatherName }) { if (!name || !isNaN(+name)) return false if (!surname || !isNaN(+surname)) return false if (!fatherName || !isNaN(+fatherName)) return false return true } }