【JavaScript】编程题 2019.08.12

本文深入探讨了JavaScript编程中的关键技巧,包括计数器、流程控制、函数特性、模块化编程、数字转换、对象操作等核心主题。通过具体示例,讲解了如何使用apply、call和bind进行函数传参,如何利用toString和parseInt进行进制转换,以及如何通过对象的hasOwnProperty方法遍历属性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

编程题:JS-计数、流程语句、函数等


1.计数

  • 实现一个打点计时器,要求
    1、从 start 到 end(包含 start 和 end),每隔 100 毫秒 console.log 一个数字,每次数字增幅为 1
    2、返回的对象中需要包含一个 cancel 方法,用于停止定时操作
    3、第一个数需要立即输出
  • 转载:husan
function count(start, end) {
    if(start <= end){
        console.log(start);
        start++;
        st = setTimeout(function(){count(start, end)}, 100);
    }
    return {
        cancel: function(){clearTimeout(st);}
    }
}

2.流程控制

  • 实现 fizzBuzz 函数,参数 num 与返回值的关系如下:
    1、如果 num 能同时被 3 和 5 整除,返回字符串 fizzbuzz
    2、如果 num 能被 3 整除,返回字符串 fizz
    3、如果 num 能被 5 整除,返回字符串 buzz
    4、如果参数为空或者不是 Number 类型,返回 false
    5、其余情况,返回参数 num
function fizzBuzz(num) {
    if(num%3==0&&num%5==0){
        return ('fizzbuzz');
    }else if(num%3==0){
        return ('fizz');
    }else if(num%5==0){
        return ('buzz');
    }else if(num==null||typeof(num)!='number'){
        return ('false');
    }else{
        return num;
    }   
}

3.函数

3.1 函数传参

  • 将数组 arr 中的元素作为调用函数 fn 的参数
  • 示例:
    在这里插入图片描述
  • 转载-希留:调用函数可以使用call或者apply这两个方法,区别在于call需要将传递给函数的参数明确写出来,是多少参数就需要写多少参数。而apply则将传递给函数的参数放入一个数组中,传入参数数组即可。
function argsAsArray(fn, arr) {
  return fn.apply(this, arr);
 }

3.2 函数的上下文

  • 将函数 fn 的执行上下文改为 obj 对象
  • 示例:
    在这里插入图片描述
  • 方法1:
function speak(fn, obj) {
     return fn.apply(obj);
}
  • 方法2:
function speak(fn, obj) {
     return fn.call(obj);
}
  • 方法3:
function speak(fn, obj) {
     return fn.bind(obj)();
}

3.3 返回函数

  • 实现函数 functionFunction,调用之后满足如下条件:
    1、返回值为一个函数 f
    2、调用返回的函数 f,返回值为按照调用顺序的参数拼接,拼接字符为英文逗号加一个空格,即 ', ’
    3、所有函数的参数数量为 1,且均为 String 类型
    在这里插入图片描述
function functionFunction(str) {
 return function(str2){
         return str+", "+str2;
     }  
 }

3.4 使用闭包

  • 实现函数 makeClosures,调用之后满足如下条件:
    1、返回一个函数数组 result,长度与 arr 相同
    2、运行 result 中第 i 个函数,即 resulti,结果与 fn(arr[i]) 相同
function makeClosures(arr, fn) {
   var result=[];
    for(var i=0;i<arr.length;i++){
      (function(i){
            result[i] = function(){
                return fn.call(null,arr[i]);
            }
        })(i);
    }
    return result;
}

3.5 二次封装函数

  • 已知函数 fn 执行需要 3 个参数。请实现函数 partial,调用之后满足如下条件:
    1、返回一个函数 result,该函数接受一个参数
    2、执行 result(str3) ,返回的结果与 fn(str1, str2, str3) 一致
  • 转载:牛客725600
function partial(fn, str1, str2) {
    var result=function(str3){
        return fn.bind(this,str1,str2)(str3);
    };
    return result;
}

bind不加后面的括号返回的是函数,加上后面的括号返回的是函数值,这也是bind和call和apply的主要区别,bind需要二次调用,而call和apply返回的是函数值,是直接调用。

3.6 使用 arguments

  • 函数 useArguments 可以接收 1 个及以上的参数。请实现函数 useArguments,返回所有调用参数相加后的结果。本题的测试参数全部为 Number 类型,不需考虑参数转换。
function useArguments() {
    var sums=0;
    for(var i=0;i<arguments.length;i++){
        sums+=arguments[i];
    }
    return sums;
}

3.7 使用apply调用函数

  • 实现函数 callIt,调用之后满足如下条件
    1、返回的结果为调用 fn 之后的结果
    2、fn 的调用参数为 callIt 的第一个参数之后的全部参数
  • 方法1,转载:我是一只小小小小菜鸟
function callIt(fn) {
    var args=[];
    for(var i=1;i<arguments.length;i++){
        args.push(arguments[i]);
    }
    //上述代码等价为var args = Array.prototype.slice.call(arguments,1);
    var result=fn.apply(null,args);
    return result;
}

因为arguments并不是真正的数组。

3.8 二次封装函数

  • 实现函数 partialUsingArguments,调用之后满足如下条件:
    1、返回一个函数 result
    2、调用 result 之后,返回的结果与调用函数 fn 的结果一致
    3、fn 的调用参数为 partialUsingArguments 的第一个参数之后的全部参数以及 result 的调用参数
  • 转载:希留
function partialUsingArguments(fn) {
     //先获取p函数第一个参数之后的全部参数
     var args = Array.prototype.slice.call(arguments,1);
     //声明result函数
     var result = function(){
         //使用concat合并两个或多个数组中的元素
         return fn.apply(null, args.concat([].slice.call(arguments)));
     }
     return result;
 }

3.9 柯里化?

  • 已知 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 的调用参数

4.模块

  • 完成函数 createModule,调用之后满足如下要求:
    1、返回一个对象
    2、对象的 greeting 属性值等于 str1, name 属性值等于 str2
    3、对象存在一个 sayIt 方法,该方法返回的字符串为 greeting属性值 + ', ’ + name属性值
function createModule(str1, str2) {
    var obj={
        greeting:str1,
        name:str2,
        sayIt:function(){
            return this.greeting +', ' +this.name;
        }
    };
  return obj;
}
  • 注意点:1)’, '为逗号+空格;2)sayIt方法中I大写(小写是i,不是L)

5.Number

5.1 二进制转换–十转二

  • 获取数字 num 二进制形式第 bit 位的值。注意:
    1、bit 从 1 开始
    2、返回 0 或 1
    3、举例:2 的二进制为 10,第 1 位为 0,第 2 位为 1
function valueAtBit(num, bit) {
    var arr=[];
    var i=0;
    while(true){
        arr.push(num%2);
        num=Math.floor(num/2);
        i++;
        if(i==bit||num==0){
            break;
        }
      //转换为2进制可以 var str = num.toString(2);  
    }
    return arr[bit-1];
}

5.2 二进制转换–二转十

  • 方法1:亲测可以,但是牛客网不行
function base10(str) {
    var s=0;
    str=str.split('');
    str.reverse();
    for(var i=0;i<str.length;i++){
        s+=str[i]*(2**i);
    }
    return s;
}
//----------------------
//str='11000000';
//console.log(base10(str));
  • 方法2:亲测可以,但是牛客网不行
function base10(str) {
    var s=0;
    for(var i=str.length-1;i>=0;i--){
        s+=str[i]*(2**(str.length-1-i));
    }
    return s;
}
function base10(str) {
 /**
        其它进制转十进制
        parseInt(str,2)
        parseInt(str,8)
        parseInt(str,16)
    */
    return parseInt(str,2);
}

5.3 二进制转换–十转二,补0至8位

  • 方法1: 亲测可以,但是牛客网不行!
function convertToBinary(num) {
    var arr=[];
    var i=0;
    while(true){
        arr.push(num%2);
        num=Math.floor(num/2);
        i++;
        if(num==0){
            break;
        }
        
    }
   while(arr.length<8){
       arr.unshift(0);
   }
   return arr.join('');
}
function convertToBinary(num) {
    var str = num.toString(2);
    while(str.length < 8) {
        str = "0" + str;
    }
    return str;
}

5.4 乘法

  • 求 a 和 b 相乘的值,a 和 b 可能是小数,需要注意结果的精度问题
  • js中相乘出现小数则会出现bug,如0.0001*3,结果0.0003 0000 0000 0000 0003,因此需要保留几位小数
  • 方法1:转载coypan
function multiply(a, b) {
    return parseFloat((a*b).toFixed(10));//转化为浮点数并保留10位
}

6.对象

6.1 批量改变对象的属性

  • 给定一个构造函数 constructor,请完成 alterObjects 方法,将 constructor 的所有实例的 greeting 属性指向给定的 greeting 变量。
function alterObjects(constructor, greeting) {
    constructor.prototype.greeting=greeting;
}

6.2 属性遍历

  • 找出对象 obj 不在原型链上的属性(注意这题测试例子的冒号后面也有一个空格~)
    1、返回数组,格式为 key: value
    2、结果数组不要求顺序
  • 转载:希留
function iterate(obj) {
     var arr = [];
     //使用for-in遍历对象属性
     for(var key in obj){
         //判断key是否为对象本身的属性
         if(obj.hasOwnProperty(key)){
             //将属性和值按格式存入数组
             arr.push(key+": "+obj[key]);
         }
     }
     return arr;
 }
  • hasOwnproperty方法能返回一个布尔值,指出一个对象是否具有指定名称的属性**。此方法无法检查该对象的原型链中是否具有该属性,该属性必须为对象本身的属性。**
  • 这里的key是自己定义的变量,而不是对象中的属性,通过变量访问属性时需要用方括号法,不能使用点表示法

7.小结

1.函数中传参常使用:apply、call和bind
2.进制转换:

 var str = num.toString(2);//10进制转换为2进制,也可以转换为任意进制
 var ins=parseInt(str,2);//2进制转为10进制,任意进制均可转换为10进制

3.通过变量访问属性时需要用方括号法,不能使用点表示法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值