Yihui’s Blog

牛客网刷题05

41. 使用 arguments

题目描述 函数 useArguments 可以接收 1 个及以上的参数。请实现函数 useArguments,返回所有调用参数相加后的结果。本题的测试参数全部为 Number 类型,不需考虑参数转换。 输入:1, 2, 3, 4 输出:10

// 方法一:直接遍历
function useArguments() {
    let count = 0
    for(let i = 0; i < arguments.length; i++) {
        count+= arguments[i]
    }
    return count
}

// 方法二:ES6,把arguments转化成数组用数组的方式相加
function useArguments() {
    return Array.from(arguments).reduce((prev, item) => prev + item, 0)
}

相关知识点:

  • arguments —— 函数参数的获取和类数组的运算。

42. 使用 apply 调用函数

题目描述 实现函数 callIt,调用之后满足如下条件 1、返回的结果为调用 fn 之后的结果 2、fn 的调用参数为 callIt 的第一个参数之后的全部参数 输入:无 输出:无

// 方法一:把参数从第一个开始截取,然后调用apply
function callIt(fn) {
    let newArr = Array.from(arguments).slice(1)
    return fn.apply(this,newArr)
}
// 同
function callIt(...arg) {
    let newArr = arg.slice(1)
    return arg[0].apply(this,newArr)
}

// 方法二:使用解构赋值获取剩余参数
function callIt(fn) {
    let [arg, ...restArg] = arguments
    return fn.apply(this, restArg)
}

相关知识点:

  • apply/arguments

43. 二次封装函数

题目描述 实现函数 partialUsingArguments,调用之后满足如下条件: 1、返回一个函数 result 2、调用 result 之后,返回的结果与调用函数 fn 的结果一致 3、fn 的调用参数为 partialUsingArguments 的第一个参数之后的全部参数以及 result 的调用参数 输入: 无 输出:无

// 方法一:用call直接扩展运算符
function partialUsingArguments(fn) {
    let args = [].slice.call(arguments,1)
    return function result(...newArgs) {
        return fn.call(this,...args,...newArgs)
    }
}

// 方法二:用apply接收数组
function partialUsingArguments(fn) {
    let args = [...arguments].slice(1);
    return function result(...newArgs) {
        return fn.apply(this,args.concat(newArgs))
    }
}

// 方法三:bind
function partialUsingArguments(fn) {
    let args = [...arguments].slice(1);
    return function result(...newArgs) {
        return fn.bind(this,...args,...newArgs)()
    }
}
 

相关知识点:

  • arguments/apply/call/bind

44. 柯里化

题目描述 已知 fn 为一个预定义函数,实现函数 curryIt,调用之后满足如下条件: 1、返回一个函数 a,a 的 length 属性值为 1(即显式声明 a 接收一个参数) 2、调用 a 之后,返回一个函数 b, b 的 length 属性值为 1 3、调用 b 之后,返回一个函数 c, c 的 length 属性值为 1 4、调用 c 之后,返回的结果与调用 fn 的返回值一致 5、fn 的参数依次为函数 a, b, c 的调用参数 输入 var fn = function (a, b, c) {return a + b + c}; curryIt(fn)(1)(2)(3); 输出 6

function curryIt(fn) {
    let len = fn.length // 函数的length就是参数个数
    let args = []
    return function (arg){
        args.push(arg)
        if(len > args.length) {
            return arguments.callee
        }
        return fn.apply(this, args)
    }
}
 

相关知识点:

  • 柯里化

函数式编程(三)—— 柯里化

  • 函数形参长度获取:fn.length

45. 或运算

题目描述 返回参数 a 和 b 的逻辑或运算结果 输入: false, true ; 输出: true

// 方法一:直接或运算符
function or(a, b) {
    return a || b
}

// 方法二:位运算中的或运算,返回0或者1,需要转化类型为布尔值
function or(a, b) {
    return a | b ? true : false
}
 

相关知识点:

  • 或运算

|| 运算符,a和b都为false,才是false,其中一个有true,就是false | 运算符,是位运算,位置上都是0才返回0,位置上有一个1就返回1,如果返回需要布尔值,需要转化

46. 且运算

题目描述 返回参数 a 和 b 的逻辑且运算结果 输入: false, true 输出: false

// 方法一:且运算符,返回布尔值
function and(a, b) {
    return a && b
}

// 方法二:位运算的且运算符,返回 0 和 1,需要转化成布尔值
function and(a, b) {
    return a & b ? true : false
}

 

相关知识点:

  • 且运算

&& 运算符,a和b都为true,才是true,其中一个有false,就是false & 运算符,是位运算,位置上都是1才返回1,位置上有一个0就返回0,如果返回需要布尔值,需要转化

47. 模块

题目描述 完成函数 createModule,调用之后满足如下要求: 1、返回一个对象 2、对象的 greeting 属性值等于 str1, name 属性值等于 str2 3、对象存在一个 sayIt 方法,该方法返回的字符串为 greeting属性值 + ’, ’ + name属性值

// 方法一:对象
function createModule(str1, str2) {
    return  {
        greeting: str1,
        name: str2,
        sayIt: function (){
            return this.greeting + ', ' + this.name
        }
    }
}

// 方法二: 构造函数
function createModule(str1, str2) {
    function Obj() {
        this.greeting = str1
        this.name = str2
    }
    Obj.prototype.sayIt = function () {
        return this.greeting + ', ' + this.name
    }
    return new Obj
}
 

相关知识点:

  • 模块化、构造函数、对象

48. 二进制转换

题目描述 获取数字 num 二进制形式第 bit 位的值。注意: 1、bit 从 1 开始 2、返回 0 或 1 3、举例:2 的二进制为 10,第 1 位为 0,第 2 位为 1 输入: 128,8 输出: 1

// 方法一:while循环
function valueAtBit(num, bit) {
    let arr = []
    while(num){
        arr.push(num % 2)
        num = Math.floor(num / 2)
    }
    return arr[bit-1]
}

// 方法二:位运算右移 >> 位数 - 1 然后取模 2
function valueAtBit(num, bit) {
    return (num >> bit - 1) % 2
}
 

相关知识点:

  • 二进制数值运算
  • 取模
  • 位运算符 左移 >> 右移 << 无符号位右移 <<<

49. 二进制转换

题目描述 给定二进制字符串,将其换算成对应的十进制数字 输入:‘11000000’ 输出:192

// 方法一:parseInt(str,2) 

// 方法二:((1 * 1) * 2 + 1 * 1) * 2 + 0 * 1 ...
function base10(str) {
    let count = 0
    for(let i = 0; i < str.length; i++) {
        count = count * 2 + str[i]*1
    }
    return count
}

// 方法三:1 * (2 ** 7) + 1 * (2 ** 6) + 0 * (2 ** 5) + ...
function base10(str) {
    let num = 0
    for(let i = 0; i < str.length; i++) {
        num += str[i] * Math.pow(2,str.length -1 - i)
    }
    return num
}
 

相关知识点:

  • 进制转换

二进制转十进制,从最高位开始乘2,十进制转二进制,除2取余后取逆向

50. 二进制转换

题目描述 将给定数字转换成二进制字符串。如果字符串长度不足 8 位,则在前面补 0 到满8位。 输入:65 输出:01000001(字符串)

// 方法一:转化之后检查位(算法思维,推荐)
function convertToBinary(num) {
    let arr = []
    while(num) {
        arr.push(num % 2)
        num = num >> 1
    }
    let str = ''
    let len = arr.length > 8 ? arr.length : 8
    for(let i = len - 1; i >= 0; i--){
        str = arr[i] ? str + '1' : str + '0'
    }
    return str
}

// 方法二:
function convertToBinary(num) {
    let arr = []
    while(num) {
        arr.push(num % 2)
        num = Math.floor(num / 2)
    }
    while(arr.length < 8) {
        arr.push('0')
    }
    return arr.reverse().join('')
}

// 方法三:使用API转化成二进制然后看缺的(尽量不要前面加字符串,性能消耗大)
function convertToBinary(num) {
    var str = num.toString(2);
    while(str.length < 8) {
        str = "0" + str;
    }
    return str;
}

// 方法四:因为padStart无法过AJ
function convertToBinary(num) {
    let arr = []
    while(num) {
        arr.push(num % 2)
        num = Math.floor(num / 2)
    }
    return arr.reverse().join('').padStart(8, '0')
}
 

相关知识点:

  • 二进制转换

还有一个就胜利了,真的是由浅到难的深度~~~~

维护与整理 · Yihui在 GitHub 上编辑