一道js面试题

一切的起源

  • 首先,先上一个原题链接

  • 然后,是题目:

编写一个javscript函数 fn,该函数有一个参数 n(数字类型),其返回值是一个数组,该数组内是 n 个随机且不重复的整数,且整数取值范围是 [2, 32]。

  • 最后,先自己写一遍,千万记得认真读题,仔细审题!!

我最初的代码

    let fn = function (n) {
        if ( n < 0) {
            return null;
        } else {
            let num = [];
            let i;
            for(i = 0; i < n; i++) {
                num[i] =(Math.random() * 31 ) + 2;
            }
            return num;
        }
    };

当然不合格啊!!!!


重新审题 && 题意分析

  • 传入fn的参数 n 必须为 正整数 ,也就是不能为别的类型的值,必须为 number 类型, 而且是大于零的,不带小数点的值

  • 输出类型为数组,而且是随机的,不能重复的

那么,出现的我问题都加重突出了,那么,修改一下吧

    let fn = function(n) {
        /*
         * 第一处修改, 增加判断
         */
        if (n < 0 || typeof n !== 'number' || n % 1 !== 0) {
            return null;
        } else {
            let num = [];
            let i;
            let j;
            let tmp;
            let flag = 0;
             /*
              * 第二处修改,增加对是否有重复的判断
              * 循环判断语句 'i = i - flag + 1' 解释:
              *   如果flag为1则表示产生的随机数与现有的数有重复,
              *   那么i的值不会增加,依旧为之前的值,数组也还在之前的位置
              */
            for (i = 0; i < n; i = i - flag + 1) {
                flag = 0;
                tmp = Math.floor((Math.random() * 31) + 2);
                if (i !== 0) {
                    for (j = 0; j <= i; j++) {
                        if (num[j] === tmp) {
                            flag = 1;
                            break;
                        }
                    }
                }
                if (flag === 0)
                    num[i] = tmp;
            }
            return num;
        }
    };

回炉重造

看到标题也知道现在还不是沾沾自喜的时候,我又回看原文,发现了还有几大问题

  • 未对 输入的 n 值进行检验 , 因为如果不能有重复的话那么 n 的值必须有一个最大值,也就是产生随机数的范围之差加一

  • 未做到 逻辑与数据分离 ,也就是说如果需要把随机数范围更改一下的话我这个代码多处都需要进行修改,这还是一个小小的函数,如果是一个巨大的项目的话那后果不堪设想

  • 缺少详细的注释 , 这样不利于别人的阅读理解

  • 不能利用一些原本就存在的数据结构, 比如过 js 有一个数据结构叫 set ,存入其中的值不能重复,这样就避免了人工判断的麻烦,也更优雅(滑稽脸 :-p)

    /**
     * 功能:获取指定个数的随机整数,范围为[2, 32]
     *
     * @param : [number] n 需要随机数的个数
     * @return: [array]  返回n个随机数的数组,如果n非法,则返回一个空数组
     */

    let fn = function (n) {
        //如果n非法,返回空数组
        if (n < 0 || typeof n !== 'number' || n % 1 !== 0) {
            return [];
        } else {

            //随机数最小值与最大值
            let minRange = 2;
            let maxRange = 32;

            //初始化一个 Set 数据类型
            let num = new Set();
            let length = maxRange - minRange + 1;
            //n非法,返回空数组
            if( n > length) {
                return [];
            }
            while(num.size < n) {
                //产生随机数加入到 Set 中
                num.add(Math.floor((Math.random() * length) + minRange));
            }
            //将Set转为Array
            return Array.from(num);
          }
    };

使用到的知识

  • typeof 判断数据类型

    • 补:数据类型:undefined,object(包含Null),boolean,number,string,symbol,function
  • Math.random() . 随机产生 [0, 1] 之间的随机数

  • Math.floor() . 向下取整,也就是 1.7 => 1, -2.3 => -3

    • 补: Math.ceil() 向上取整
    • 补: Math.round() 四舍五入
  • Set() . 用来存储没有重复的数据


反思

  • 我的js好垃圾
  • 在写代码之前作出详尽的需求分析
  • 对输入的值判断要做到足够精细
  • 做到 逻辑与数据分离 十分重要
  • 要写详尽的注释
  • 尽量使用已经存在的工具,不要重复造轮子,除非万不得已

你可能感兴趣的:(javascript,面试)