第十六天
(题目来源: 前端每日知识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);
// }
// 用call
function 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]); //apply
return 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] = arguments
return 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)()); //7
console.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()`
可遍历, 去重
第五种使用`...`
扩展运算符