美文网首页
牛客网前端大挑战题解

牛客网前端大挑战题解

作者: 立的flag一直在倒 | 来源:发表于2018-11-07 21:37 被阅读0次

    一、获取 url 中的参数
    1. 指定参数名称,返回该参数的值 或者 空字符串
    2. 不指定参数名称,返回全部的参数对象 或者 {}
    3. 如果存在多个同名参数,则返回数组

    看到牛客一位大神的代码非常简洁,如下:

    function getUrlParam(sUrl, sKey) {
          var result = {};
          // replace()方法的参数replacement可以是函数。此时,每个匹配都调用该函数,它返回的字符串将作为替换文本使用。
          // 该函数的第一个参数是匹配模式的字符串,接下来的参数是与模式中的子表达式匹配的字符串,可以有0个或多个。
          // 再接下来的参数是一个整数,声明了匹配在stringObject中出现的位置,最后一个参数是stringObject本身
          sUrl.replace(/\??(\w+)=(\w+)&?/g, function (a, k, v) {
            // console.log(a);
            // console.log(k);
            // console.log(v);
            // void 0 === undefined, void 0比undefined占用的字节少,多用在压缩文件上
            if (result[k] !== void 0) {
              var t = result[k];
              result[k] = [].concat(t, v);
            } else {
              result[k] = v;
            }
          });
          if (sKey === void 0) {
            return result;
          } else {
            return result[sKey] || '';
          }
        }
    console.log(getUrlParam("http://www.baidu.com/#/?t1=1&t3=2&t5=3"));
    

    打印出来的a, k, v的值和最后结果如下:

    打印结果
    a对应匹配的字段,k对应参数,v对应参数值。
    对于replace结合正则表达式的运用,可以看一下这篇:replace()结合正则表达式

    二、根据包名,在指定空间中创建对象
    如题:根据包名,在指定空间中创建对象
    输入描述:namespace({a: {test: 1, b: 2}}, 'a.b.c.d')
    输出描述:{a: {test: 1, b: {c: {d: {}}}}}

    通俗说,就是:根据包名,比较指定空间中有没有与包名对应的对象,有则保留,无则创建一个空对象。

        function isObj(value) {
          return Object.prototype.toString.call(value) == "[object Object]";
        }
    
        function namespace(oNamespace, sPackage) {
          var scope = sPackage.split('.');
          var ns = oNamespace;
          for (var i = 0; i < scope.length; i++) {
            if (!ns.hasOwnProperty(scope[i]) || !isObj(ns[scope[i]])) {
              ns[scope[i]] = {};
            }
            ns = ns[scope[i]];
          }
          return oNamespace;
        }
        console.log(namespace({ a: { test: 1, b: 2 } }, 'a.b.c.d'));
    

    这里有两点需要注意:
    1、判断指定空间里是否存在于包名对应的对象,用hasOwnProperty判断是否存在,如果存在,接着判断是否为对象,正确的判断是:Object.prototype.toString.call(value) == "[object Object]";
    2、对最后直接return oNamespace;的理解:Object是引用赋值,将对象赋值给某个变量,实际上相当于把指向引用类型的地址指针赋予给这个变量。两个变量都指向了堆内存中的同一个对象,他们中任何一个做出的改变都会反应在另一个身上。

    三、数组去重
    输入:[false, true, undefined, null, NaN, 0, 1, {}, {}, 'a', 'a', NaN]
    输出:[false, true, undefined, null, NaN, 0, 1, {}, {}, 'a']
    可以看出,需要对NaN去重, {}则不需要
    1、使用indexOf()方法

        Array.prototype.uniq = function (){
          var newarr = [];
          var flag = true;
          for(var i = 0;i < this.length;i++) {
            if(newarr.indexOf(this[i]) == -1) {
              if(this[i] != this[i]) {
                if(flag) {
                  newarr.push(this[i]);
                  flag = false;
                }
              }else {
                newarr.push(this[i]);
              }
            }
          }
          return newarr;
        }
    

    需要注意的点:
    在indexOf判断中,NaN和空对象{}均返回-1,需要单独判断。而NaN和{}又有区别:

    var a = NaN;
    var b = NaN;
    var c = {};
    var d = {};
    console.log(a == b);    // false
    console.log(c == d);    // false
    console.log(a == a);    // false
    console.log(c == c);    // true
    

    以上代码可以看出:NaN != NaN, {} != {},但NaN不等于它自己本身,{}会等于自己本身,可以以此来区分NaN和{}, 对NaN去重。
    2、ES6 的Set方法

    Array.prototype.uniq = function () {
        return [...new Set(this)];
    }
    

    有兼容性问题
    3、使用splice直接在数组本身操作

        Array.prototype.uniq = function() {
          var hasNaN = false;
          for(var i = 0;i < this.length;i++) {
            if(this[i] !== this[i]) {
              hasNaN=true;
            }
            for(var j = i+1;i < this.length;) {
              if(this[i] === this[j] || (hasNaN && this[j] !== this[j])) {
                this.splice(j, 1);
              }else{
                j++;
              }
            }
          }
          return this;
        }
    

    四、时间格式化输出
    描述:
    按所给的时间格式输出指定的时间
    格式说明
    对于 2014.09.05 13:14:20
    yyyy: 年份,2014
    yy: 年份,14
    MM: 月份,补满两位,09
    M: 月份, 9
    dd: 日期,补满两位,05
    d: 日期, 5
    HH: 24制小时,补满两位,13
    H: 24制小时,13
    hh: 12制小时,补满两位,01
    h: 12制小时,1
    mm: 分钟,补满两位,14
    m: 分钟,14
    ss: 秒,补满两位,20
    s: 秒,20
    w: 星期,为 ['日', '一', '二', '三', '四', '五', '六'] 中的某一个,本 demo 结果为 五
    输入: formatDate(new Date(1409894060000), 'yyyy-MM-dd HH:mm:ss 星期w')
    输出: 2014-09-05 13:14:20 星期五

      function formatDate(oDate, sFormation) {
          var obj = {
            yyyy: oDate.getFullYear(), 
            yy: ("" + oDate.getFullYear()).slice(-2),
            M: oDate.getMonth() + 1,
            MM: ("" + (oDate.getMonth()+1)).slice(-2),
            d: oDate.getDate(),
            dd: ("0" + oDate.getDate()).slice(-2),
            H: oDate.getHours(),
            HH: ("0" + oDate.getHours()).slice(-2),
            h: oDate.getHours() % 12,
            hh: ("0" + oDate.getHours() % 12).slice(-2),
            m: oDate.getMinutes(),
            mm: ("0" + oDate.getMinutes()).slice(-2),
            s: oDate.getSeconds(),
            ss: ("0" + oDate.getSeconds()).slice(-2),
            w: ['日', '一', '二', '三', '四', '五', '六'][oDate.getDay()]
          };
          return sFormation.replace(/([a-z]+)/ig, function($1){return obj[$1]});
        }
    
        console.log(formatDate(new Date(1409894060000),'yy-MM-dd HH:mm:ss 星期w'));
    

    $1 表示正则表达式第一个小括号中匹配项的值。

    比如 /gai([\w]+?)over([\d]+)/
    匹配 gainover123
    $1= 括号里的 n
    $2= 第2个括号里的 123
    

    相关文章

      网友评论

          本文标题:牛客网前端大挑战题解

          本文链接:https://www.haomeiwen.com/subject/bmtdbftx.html