• TOM大叔的几道Javascript题目与解答


    几道JS题目

    之前没有深入研究js语言,最近几年前端越来越工程化,需要扎实的js基础,看到博客园上有很多大牛分享JS学习文章,幸运看到tom大叔的blog,抽时间潜心学习了其文章,遇到到其出的几道题目,尝试自己解决,以测试自己的js水平。

    http://www.cnblogs.com/TomXu/archive/2012/02/10/2342098.html

    1. 找出数字数组中最大的元素(使用Match.max函数)
    2. 转化一个数字数组为function数组(每个function都弹出相应的数字)
    3. 给object数组进行排序(排序条件是每个元素对象的属性个数)
    4. 利用JavaScript打印出Fibonacci数(不使用全局变量)
    5. 实现如下语法的功能:var a = (5).plus(3).minus(6); //2
    6. 实现如下语法的功能:var a = add(2)(3)(4); //9

    找出数字数组中最大的元素(使用Match.max函数)

    问题棘手点在 Math.max的入参是离散的, 即时,函数的参数一一列举, 逗号隔开, 形式如 Math.max(a,b,c)。

    但是只凭js,没有任何一种方法,将数组离散化后,再传给Math.max方法, 如果数组为 后台变量还可以使用后台离散方法,写法为 Math.max(<%=arr.join(“,”)%>)。

    对于函数和参数的考虑,我们往往能够想到, 一个使得参数变换调用方式的方法, func.apply(obj, argArr) == func.call(obj, arg1, arg2,…)

    即 apply 调用能够使得参数组织为数组形式, 但是调用后, 其效果等价于 参数列举形式。

    但是其第一个参数为函数中this指代的对象, 如果一个函数其中没有this使用, 则可以使用apply方式, 满足函数定义为参数列举, 但是实际参数为数组的情况。实现代码:

    var numArr = [

      1,
      2,
      44
    ];
    console.log(Math.max.apply(null, numArr))

    注意 其中apply第一个参数为 null 或者 undefined, 表示如果max函数中有this应用,则this指代宿主对象, window。

    执行结果:

    image

    进一步延伸

    如果有一个函数,只有一个参数, 要求为数组, 但是应用中需要按照参数列举(每个参数为数组元素)方式使用此函数,则如何是好?

    看如下方法:

    1、 test函数接受一个入参, 要求是数组,此函数将打印数组中每个元素。

    2、 我们首先想到, call可以将列举参数 收集到 函数的 arguments 对象中, 但是如果使用 test.call(null, 1, 3), 则需要test函数针对arguments做直接取值操作(arguments[index])), 与其内部已经实现的代码逻辑不一致:

    function test(){
      for(var index in arguments){
         console.log(arguments[index])
      }
    }

    实际上arguments是一个对象, 而且是 Array-like类型的, 这是什么玩意?请见 http://tunps.com/javascript-array-like-object

    这种类型,可以使用 Array.prototype.slice 函数将其转换为真正的数组。转换为数组后,就满足test函数参数定义规则了。 完整代码如下:

    // test 入参为一个数组
    function test(){
      for(var index in arguments[0]){
         console.log(arguments[0][index])
      }
    }
    test([1, 3]);


    //test.call(null, 1, 3);  // need test use arguments[index] to get value

    // 将 1, 3, 3 转换为素组调用
    function testCall(){
       test(Array.prototype.slice.call(arguments))
    }

    testCall(1, 3);

    执行结果:

    image

    转化一个数字数组为function数组(每个function都弹出相应的数字)

    主要考察闭包用法(闭包可以构造一个保留执行现场状态的小环境,并且每次访问闭包函数,都能够访问和设置此小环境)。

    比较基础,直接上代码:

    var numArr = [
      1,
      2,
      44
    ];


    for (i in numArr)
    {
      numArr[i] = (function(num){
        return function()
        {
          console.log(num)
        }
      })(numArr[i]);
    }


    for (i in numArr)
    {
      numArr[i]();
    }

    执行结果:

    image

    给object数组进行排序(排序条件是每个元素对象的属性个数)

    通过属性访问区分(hasOwnProperty),考虑对原型概念的理解, 并且对数组为引用类型的理解。

    代码:

    var numArr = [
      {"a":"b"},
      {"a":"b", "oo":"pp", "uu":"qq"},
      {"a":"b", "ll":"b"}
    ];


    console.log("numArr is Array="+(numArr instanceof Array))


    var i = 0
    var tmp = numArr[i];
    console.log("tmp="+tmp)

    //获取对象自身属性个数
    function GetPropertyNum(obj){
      var num = 0;
      for (var key in obj){
        if ( obj.hasOwnProperty(key) )
        {
            num ++;
        }
      }
      return num;
    }


    // test GetPropertyNum
    console.log(GetPropertyNum({"a":"b"}))


    //使用冒泡排序
    function BubbleSort(arr, cmpFunc)
    {
      for( var i=0; i<=arr.length-2; i++ )
      {
        for ( var j=0; j<=arr.length-2-i; j++ )
        {
          //前一个大于后一个
          var pre = arr[j];
          var next = arr[j+1];
          if ( cmpFunc(pre,next) > 0 )
          {
             var tmpObj = arr[j];
             arr[j] = arr[j+1];
             arr[j+1] = tmpObj;
          }
        }
      }
    }

    // 对象属性数目大小比较函数
    function ObjectPropertyCmp(obj1, obj2)
    {
      var preCount = GetPropertyNum(obj1);
      var nextCount = GetPropertyNum(obj2);
      if ( preCount > nextCount )
      {
        return 1;
      }
      else if ( preCount === nextCount )
      {
        return 0;
      }
      else
      {
        return -1
      }
    }


    console.log("----- before buble sort -----------")
    for (var i in numArr){
      console.log(numArr[i]);
    }

    BubbleSort(numArr, ObjectPropertyCmp);

    console.log("----- after buble sort -----------")
    for (var i in numArr){
      console.log(numArr[i]);
    }

    执行结果:

    image

    利用JavaScript打印出Fibonacci数(不使用全局变量)

    考察闭包实现执行过程状态保存的功能。

    代码:

    // 创建fibonaci生成器, 生成闭包, 存储 prev 和 current环境

    function createFibonaci()
    {
      var prev = 0;
      var current = 1;
      return function(){
        var result = prev + current;
        prev = current;
        current = result;
        return current;
      }
    }

    //按照下标打印fibonaci数列
    function printFibonaci(order)
    {
      var fiboArr = [0, 1];
      var fibonaciGenerator = createFibonaci();
      for( var i=2; i<=order; i++ )
      {
        fiboArr.push(fibonaciGenerator());
      }
      for ( var i in fiboArr )
      {
        console.log("fibo index="+i+"; fibonum="+fiboArr[i]);
      }
    }


    printFibonaci(8);

    执行结果:

    image

    实现如下语法的功能:var a = (5).plus(3).minus(6); //2

    考察基本数据类型, 以及和对应对象的关系, 并在原型中添加新方法的让特定对象支持新特性。

    (5). xxx 将会把5转换为 对象, 相当于 (new Number(5)).xxx

    xxx (plus) 是不存在的, 则需要在 Number原型中添加plus方法, Number.prototype.plus = ??

    plus方法调用后,还可以调用minus方法, 则plus函数返回一个 数值基本数据类型的变量, 同时minus也需要在Number原型中添加。

    上代码,请细品:

    // Number类型值转换为 Number对象
    var numObj = new Number(5);
    console.log("numObj type="+typeof numObj);


    // Number对象获取 Number类型值
    var num = numObj.valueOf();
    console.log("num = "+num);
    console.log("num type="+typeof num);


    Number.prototype.plus = function(num){
      var thisNum = this.valueOf();
      return thisNum + num;
    }


    Number.prototype.minus = function(num){
      var thisNum = this.valueOf();
      return thisNum - num;
    }


    var a = (5).plus(3).minus(6);
    console.log("a="+a);

    执行结果:

    image

    实现如下语法的功能:var a = add(2)(3)(4); //9

    考察 闭包 + 原型链(函数重载)+对象取值函数valueOf等概念。

    首先,  add是一个函数, 观察其后有 2 3 4, 结果又为9 , 大概意思为分三次相加, 值能够保存在某个地方。

    其次, add(2) 后面 有  (3), 则表示 add(2) 返回的 也是一个函数, 记为 func, 则add(2)(3) == func(3), 此func也有add的功能,是将3加到add(2)保存的变量中,则让人联想到 add是闭包产生。

    最后, xxx(4)之后, 其 被赋值给 变量 a, 从前面分析知道 xxx(4)应该返回也是一个函数, 这个函数具有add的功能, 则函数如何取得其值呢? 有请对象的valueOf方法出场。(这个add明明是函数, 对什么说其是对象,并拥有对象的valueOf方法呢? 请看 http://www.cnblogs.com/wangfupeng1988/p/3979533.html

    上代码:

    function createAddFunc()
    {
      var sum = 0;

      function add(num){
        sum += num;
       
        return add;
      };

      add.valueOf = function(){
          return sum; 
      };
       
      return add;
    }


    var add = createAddFunc();

    var a = add(2)(3)(4);

    console.log("a="+a);//a = 9

    执行结果:

    image

    完结,真正研究过,确实学到不少东西。感谢大叔出题。

    博客园上有其他同学,做过,附上做参考吧,(不论好坏,每天daydayup即可,欢迎指正):

    http://www.cnblogs.com/yanyd/p/4202583.html

  • 相关阅读:
    Windows环境安装tesseract-ocr 4.00并配置环境变量
    iis6手工创建网站后无法运行php脚本
    spring boot集成websocket实现聊天功能和监控功能
    spring boot2.0.4集成druid,用jmeter并发测试工具调用接口,druid查看监控的结果
    springboot2.1.5集成单节点elasticsearch6.4.0
    spring boot集成netty-服务端和客户端demo
    spring boot集成mongo统计活跃用户数
    spring boot集成swagger,自定义注解,拦截器,xss过滤,异步调用,定时任务案例
    spring cloud分布式配置中心案例
    spring cloud--zuul网关和zuul请求过滤
  • 原文地址:https://www.cnblogs.com/lightsong/p/4753427.html
Copyright © 2020-2023  润新知