目录
-
引言
- 正确的函数定义 (简单)
- 正确的使用 parseInt (入门)
- 完全等同 (入门)
- 计时器 (中等)
- 流程控制 (中等)
- 函数传参 (入门)
- 函数的上下文 (入门)
- 返回函数 (简单)
- 使用闭包 (中等)
- 二次封装函数 (入门)
引言
牛客网这个前端笔试题库,可以说这60道是最基础的了,也是考察的东西比较杂,有时间4天差不多就可以刷完,巩固基础还是有些用的。做完题回顾一上午就可以过完一遍。现在我结合我的答案和参考的其他人的答案,在这里做一个总结,也是自己知识的整理结果。
- 前端刷题 —— 牛客网前端题库60道详解(一)
- 前端刷题 —— 牛客网前端题库60道详解(二)
- 前端刷题 —— 牛客网前端题库60道详解(三)
- 前端刷题 —— 牛客网前端题库60道详解(四)
- 前端刷题 —— 牛客网前端题库60道详解(五)
- 前端刷题 —— 牛客网前端题库60道详解(六)
31. 正确的函数定义
题目描述
请修复给定的 js 代码中,函数定义存在的问题
输入:true
输出:afunction functions(flag) { if (flag) { function getValue() { return 'a'; } } else { function getValue() { return 'b'; } } return getValue(); }
// 方法一:使用函数表达式
function functions(flag) {
if (flag) {
var getValue = () => { return 'a'; }
} else {
var getValue = () => { return 'b'; }
}
return getValue();
}
// 上面的等同于下面的,变量提升
function functions(flag) {
var getValue
if (flag) {
getValue = () => { return 'a'; }
} else {
getValue = () => { return 'b'; }
}
return getValue();
}
相关知识点:
- 函数的定义方式
函数声明式:函数声明在函数没有执行之前就已经在作用域中会提升,同名的声明会进行覆盖,以下面的为准,那么程序执行的时候一直输出的就是b。
函数表达式:使用函数表达式,还是会进行变量的提升,只不过这次提升的是变量getValue,在执行的时候,才会根据if语句的流程控制执行不同的函数。
31. 正确的使用 parseInt
题目描述
修改 js 代码中 parseInt 的调用方式,使之通过全部测试用例
输入:'12' 输出:12
输入: '12px' 输出:12
输入: '0x12' 输出:0
// 方法,确定是10进制
function parse2Int(num) {
return parseInt(num,10);
}
相关知识点:
- parseInt
parseInt经常用于强制类型转换中显式转换成数字,接收两个参数,返回数值或者NaN
parseInt(string, radix)
第一个参数是字符串,必须传的。
第二个参数是数字的基数,2-36,如果不传或者传0都是以10位基数来计算,如果小于2(不等于0)或者大于36一律返回NaN,如果'0x'开头为16进制,'0'开头不包括0是8进制。parseInt强制类型转化的时候,如果第一位不是数字就会返回NaN,如果第一位是数字,那么会把后面是数字的返回,不是数字的过滤掉。如果是小数的话,会向下取整成整数。
33. 完全等同
题目描述
判断 val1 和 val2 是否完全等同
function identity(val1, val2) {
return val1 === val2
}
相关知识点:
- 等同
== 和 === 的区别,简单来说在于,== 只判断值相同,遇到问题,=== 还要判断类型是否相同。
这里其实我觉得还需要考虑NaN的问题,NaN !== NaN
31. 正确的函数定义
题目描述
实现一个打点计时器,要求
- 从 start 到 end(包含 start 和 end),每隔 100 毫秒 console.log 一个数字,每次数字增幅为 1
- 返回的对象中需要包含一个 cancel 方法,用于停止定时操作
- 第一个数需要立即输出
function count(start, end) {
// 第一个立即输出
console.log(start++)
let time = setInterval(function () {
if(start >= end) clearInterval(time)
console.log(start++)
},100)
return {
// 返回的方法是一个函数
cancel: function () {
clearInterval(time)
}
}
}
相关知识点:
- setInterval
计时器,如果第一个要立即输出,那么需要手动写一次。
定义的时候接收两个参数,第一个是每次执行的函数,第二个是执行时间间隔。
返回值接收计时器名称,可以用于清空计时器用。
- 闭包
31. 流程控制
题目描述
实现 fizzBuzz 函数,参数 num 与返回值的关系如下:
1、如果 num 能同时被 3 和 5 整除,返回字符串 fizzbuzz
2、如果 num 能被 3 整除,返回字符串 fizz
3、如果 num 能被 5 整除,返回字符串 buzz
4、如果参数为空或者不是 Number 类型,返回 false
5、其余情况,返回参数 num
输入: 15 ; 输出: fizzbuzz
function fizzBuzz(num) {
// 如果num为空或者不传,isNaN都为true
if(isNaN(num)) return false
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
}
}
相关知识点:
- 流程控制:if-else
- isNaN
isNaN(),遇到不是Number类型的判断都用这个函数,如果参数不是数字就返回true,其他的判断我觉得都不是这个题要考的。ES6之后新增了方法Number.isNaN() 判断是否是NaN
- 取余 %
36. 函数传参
题目描述
将数组 arr 中的元素作为调用函数 fn 的参数
输入:
function (greeting, name, punctuation) {return greeting + ', ' + name + (punctuation || '!');}, ['Hello', 'Ellie', '!']
输出:
Hello, Ellie!
// 方法一:量身定做,传的是数组
function argsAsArray(fn, arr) {
return fn.apply(this,arr)
}
// 方法二:如果用call就需要使用扩展符打散
function argsAsArray(fn, arr) {
return fn.call(this,...arr)
}
// 方法三:如果bind处理
function argsAsArray(fn, arr) {
return fn.bind(this,...arr)()
}
相关知识点:
- apply/call/bind (详情见一的第一题)
- fn传参问题
37. 函数的上下文
题目描述
将函数 fn 的执行上下文改为 obj 对象
输入:
function () {return this.greeting + ', ' + this.name + '!!!';}, {greeting: 'Hello', name: 'Rebecca'}
输出:Hello, Rebecca!!!
// 方法一:apply
function speak(fn, obj) {
return fn.apply(obj)
}
// 方法一:call
function speak(fn, obj) {
return fn.call(obj)
}
// 方法一:bind
function speak(fn, obj) {
return fn.bind(obj)()
}
相关知识点:
- this指向
apply/call/bind 都可以修改执行上下文,如果直接调用fn,this指的是window,如果用 apply/call/bind 可以将this改成对象obj
38. 返回函数
题目描述
实现函数 functionFunction,调用之后满足如下条件:
1、返回值为一个函数 f
2、调用返回的函数 f,返回值为按照调用顺序的参数拼接,拼接字符为英文逗号加一个空格,即 ', '
3、所有函数的参数数量为 1,且均为 String 类型
输入:
functionFunction('Hello')('world')
输出: Hello, world
function functionFunction(str) {
return function f(...arg) {
// 记得逗号之后要加一个空格,才能过oj
return str + ', '+arg
}
}
相关知识点:
- 闭包 + 柯里化
闭包的作用是一个函数可以访问另一个函数作用域的变量。
39. 使用闭包
题目描述
实现函数 makeClosures,调用之后满足如下条件:
1、返回一个函数数组 result,长度与 arr 相同
2、运行 result 中第 i 个函数,即result[i]()
,结果与fn(arr[i])
相同
输入:[1, 2, 3], function (x) { return x * x; }
输出:4
// 闭包
function makeClosures(arr, fn) {
let result = []
for(let i = 0; i < arr.length; i++) {
result.push(function(){
return fn(arr[i])
})
}
return result
}
相关知识点:
- 闭包
上面的题,如果不用闭包,那么for循环的嘶吼,最后调用函数的时候,i都是arr.length,如果使用闭包,可以是当时循环的i值。
40. 二次封装函数
题目描述
已知函数 fn 执行需要 3 个参数。请实现函数 partial,调用之后满足如下条件:
1、返回一个函数 result,该函数接受一个参数
2、执行 result(str3) ,返回的结果与 fn(str1, str2, str3) 一致
输入:
var sayIt = function(greeting, name, punctuation) { return greeting + ', ' + name + (punctuation || '!'); }; partial(sayIt, 'Hello', 'Ellie')('!!!');
输出:Hello, Ellie!!!
// 方法一:直接调用,因为没有涉及到this,这里直接用arguments来获取,因为arguments是类数组
function partial(fn, str1, str2) {
return function result() {
return fn(str1,str2,arguments[0])
}
}
// 方法二:用扩展运算符拿到参数传入,更加的通用
function partial(fn, str1, str2) {
return function result(...arg) {
return fn(str1,str2,arg)
}
}
// 方法二:ES6箭头函数,this指的是undefined
const partial = (fn, str1, str2) => str3 => fn(str1, str2, str3)
相关知识点:
- 闭包
- 获取函数参数arguments
arguments 类数组,
获取长度arguments.length
获取元素用数组下标arguments[0]
获取当前执行的函数 arguments.callee (ES5严格模式下禁用)
后面的东西可能会上一些小难度~~~