zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    tensorflow 2.0 学习 (十) 拟合与过拟合问题
    tensorflow 2.0 学习 (九) tensorboard可视化功能认识
    tensorflow 2.0 学习 (八) keras模块的认识
    tensorflow 2.0 学习 (七) 反向传播代码逐步实现
    tensorflow 2.0 学习 (六) Himmelblua函数求极值
    tensorflow 2.0 学习 (五)MPG全连接网络训练与测试
    arp协议简单介绍
    Pthread spinlock自旋锁
    线程和进程状态
    内核态(内核空间)和用户态(用户空间)的区别和联系·
  • 原文地址:https://www.cnblogs.com/lightsong/p/4753427.html
Copyright © 2011-2022 走看看