第十六天
(题目来源: 前端每日知识3+1)
Javascript题目1
题目: 实现一个打点计时器(js)
问题解答1
- 从start到end (包含start和end), 每隔100毫秒console.log 一个数字,每次数字增幅为1
- 返回的对象中需要包含一个 cancel方法,用于停止定时操作
- 第一个数需要立即输出
解题思路1
setTimeout方法+递归
let timer;function countFn(start, end) {clearTimeout(timer) // 调用函数之前执行一次清除定时器,以免影响下一次 定时操作console.log(start++);timer = setTimeout(() => {if (start <= end) {return countFn(start, end)}return {clear() {clearTimeout(timer)}}}, 100)}countFn(4, 9)
setInterval方法
let timer;function countFn(start, end) {//立即输出第一个值console.log(start++);timer = setInterval(function() {if (start <= end) {console.log(start++);} else {clearInterval(timer);}}, 100);//返回一个对象return {cancel() {clearInterval(timer);}};}countFn(4, 9)
Javascript题目2
题目: 实现fizzBuzz函数, 参数num与返回值的关系如下(js)
问题解答2
- 如果num能同时被3和5整除, 返回字符串
fizzbuzz - 如果num能被3整除, 返回字符串
fzz - 如果num能被5整除, 返回字符串
buzz - 如果参数为空或者不是Number类型, 返回false
- 其余情况, 返回参数num
解题思路2
function fizzBuzz(num) {if (isNaN(num) || typeof num !== Number || num.length == 0) return false;// Object.prototype.toString.call(num).match(/(?<=\[object\s)(\w*)(?=\])/g)[0]if (num % 3 == 0 && num % 5 == 0) {return 'fizzbuzz'} else if (num % 3 == 0) {return 'fizz'} else if (num % 5 == 0) {return 'buzz'} else {return num}}console.log(fizzBuzz('2'));
Javascript题目3
题目: 将数组arr中的元素作为调用函数fn的参数(js)
问题解答3
解题思路3
// function argsAsArray(fn, arr) {// return fn(arr[0], arr[1], arr[2]);// }// 用apply// function argsAsArray(fn, arr) {// return fn.apply(fn, arr);// return fn.apply(this, arr);// }// 用callfunction argsAsArray(fn, arr) {return fn.call(this, arr[0], arr[1], arr[2]);//return fn.call(fn, arr[0], arr[1], arr[2]);}// 使用扩展运算符的方法function argsAsArray(fn, arr) {return fn(...arr);}console.log(argsAsArray(function(params, name, punc) {return `${params},${name + punc}`}, ['hello', 'world', '!']));
Javascript题目4
题目: 已知函数fn执行需要三个参数, 请实现函数partial, 调用之后满足以下条件(js)
问题解答4
- 返回一个函数result,该函数接收一个参数
- 执行result(str3),返回的结果与fn(str1, str2, str3)一致
- 输入
var sayIt = function(greeting, name, punctuation) {return greeting + ',' + name + (punctuation || '!');};partial(sayIt, 'Hello', 'Ellie')('!!!');
- 输出
Hello, Ellie!!!
解题思路4
bind方法
// 第一种方法function partial(fn, str1, str2) {// return result=(str3)=>fn.bind(this, str1, str2)(str3); // bind fn.bind(this, str1, str2)// return result = (str3) => fn.apply(this, [str1, str2, str3]); //applyreturn result = (str3) => fn.call(this, str1, str2, str3); // call}// 第二种方法let partal = (fn, str1, st2) => result = (str3) => fn(str1, str2, str3)
Javascript题目5
题目: 函数useArguments可以接收1个及以上的参数. 请实现函数useArguments, 返回所有调用参数相加后的结果. 本题的测试参数全部为Number类型, 不需考虑参数转换.(js)
问题解答5
解题思路5
// function userArguments(...arg) {// return [...arg].reduce((init, pre) => init + pre)// }function userArguments() {// 第一种// let arr = Array.prototype.slice.call(arguments)// 第二种// let arr = [].slice.call(arguments)// 第三种// let arr = Array.from(arguments)// 第四种// let arr = [...arguments]// return eval(arr.join("+"))// 第五种 在传入的参数不重复的情况下使用// let result = 0;// for (let i of new Set(arguments).values()) {// result += i// }// return result// 第六种return Array.prototype.reduce.call(arguments, (a, b) => a + b)}console.log(userArguments(1, 2, 3, 2, 1));
Javascript题目6
题目: 实现函数 callIt, 调用之后满足如下条件(js)
问题解答6
- 返回的结果为调用 fn 之后的结果
- fn 的调用参数为 callIt 的第一个参数之后的全部参数
解题思路6
// 解构方法function calllt(fn) {let [f, ...arg] = argumentsreturn f.apply(this, arg)}// slice// function calllt(fn) {// return fn.apply(this, Array.prototype.slice.call(arguments, 1))// }console.log(calllt(function() {return [...arguments].reduce((a, b) => a + b)}, 2, 1, 3, 2)); //8
Javascript题目7
题目: 实现函数 partialUsingArguments, 调用之后满足如下条件(js)
问题解答7
- 返回一个函数 result
- 调用 result 之后,返回的结果与调用函数 fn 的结果一致
- fn 的调用参数为 partialUsingArguments 的第一个参数之后的全部参数以及 result 的调用参数
解题思路7
function partialUsingArguments(fn) {//先获取p函数第一个参数之后的全部参数var args = [].slice.call(arguments, 1);//声明result函数return result = function() {//使用concat合并两个或多个数组中的元素return fn.apply(this, args.concat([].slice.call(arguments)));};}function fn() {return [...arguments].reduce((a, b) => a + b)}console.log(partialUsingArguments(fn, 2, 3, 2)()); //7console.log(fn(2, 3, 2)); //7
Javascript题目

问题解答
// 第一种方法 本方法// function currylt(fn) {// console.log(fn.length);// return a = (str1) => {// return b = (str2) => {// return c = (str3) => {// return fn.apply(null, [str1, str2, str3])// }// }// }// }// 第二种柯里化方法let args = [];function currylt(fn) {let a = (arg) => {args.push(arg)if (args.length < fn.length) {return a} else {return fn.apply(null, args)}}return a}var fn = function(a, b, c) {return a + b + c;}console.log(currylt(fn)(1)(2)(3));console.log(fn(1, 2, 3));
解题思路
- 柯里化是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数, 并且返回接受余下的参数且返回结果的新函数的技术.
知识扩展
- apply和call方法都是改变this的指向, apply接受两个参数一个是函数运行的作用域(this), 还有一个就是数组; call接受一个或者多个参数, 与apply不同的是, 传递给函数的参数必须列举出来
- bind与以上方法类似, 使用bind函数会创建一个新的函数, 可以改变参数的结构, bind不是立即执行, 未传入参数时, 并未执行, 只是返回一个函数, 等待参数传入
- 将arguments类数组转换成正常的数组的方法
第一种使用`Array.prototype.slice.call(arguments)`将函数传入的具有length对象转换成数组的形式第二种是`[].slice.call(arguments)`与上面的方法等价第三种使用es6语法`Array.from()`方法可以将类数组转换成正常的数组第四种`new Set()`可遍历, 去重第五种使用`...`扩展运算符
