前端大挑战


前端大挑战

修改this指向

题目描述

封装函数 f,使 f 的 this 指向指定的对象

代码:
// 第一种
function bindThis(f, oTarget) {
    return function() {
        return f.apply(oTarget, arguments);
    }
}

// 第二种
function bindThis(f, oTarget) {
    return f.bind(oTarget);
}

// 第三种
function bindThis(f, oTarget) {
    let args = Array.prototype.slice.call(arguments, 2);
    return function(){
        return f.apply(oTarget, Array.prototype.slice.call(arguments).concat(args));
    }
}

获取 url 中的参数

题目描述
  1. 指定参数名称,返回该参数的值 或者 空字符串
  2. 不指定参数名称,返回全部的参数对象 或者 {}
  3. 如果存在多个同名参数,则返回数组
// 输入
http://www.nowcoder.com?key=1&key=2&key=3&test=4#hehe key
// 输出
[1, 2, 3]
思路:

给定一个url为http://www.nowcoder.com?key=1&key=2&key=3&test=4#hehe key,首先根据#截取字符串url的前半部分,即``http://www.nowcoder.com?key=1&key=2&key=3&test=4`,然后再通过`?`截取`url`参数,即`key=1&key=2&key=3`,接着分情况讨论:

  • 当指定参数名称时,首先对上边处理获得的参数字符串通过&进行分割,得到一个字符串数组,如["key=1", "key=2", "key=3"],对该字符串数组进行遍历,先对遍历到的当前字符串通过=进行分割,得到的结果记为tmp,判断该字符串是否与指定的参数名称相等,如果相同,则将其添加到数组中。遍历结束之后,如果数组长度为2,则直接返回值,如果长度为0,则直接返回空字符串。

  • 当不指定参数时,大致流程同上,最后通过判断返回全部的参数对象 或者 {}

    代码:
function getUrlParam(sUrl, sKey) {
    var param = sUrl.split('#')[0].split('?')[1];
    if (sKey){//指定参数名称
        var strs = param.split('&');
        var arrs = new Array();//如果存在多个同名参数,则返回数组
        for(var i = 0, len = strs.length; i < len; i++){
            var tmp = strs[i].split('=');
            if(tmp[0] == sKey){
                arrs.push(tmp[1]);
            }
        }
        if (arrs.length == 1){//返回该参数的值或者空字符串
            return arrs[0];
        } else if (arrs.length == 0){
            return "";
        } else {
            return arrs;
        }
    } else {//不指定参数名称,返回全部的参数对象 或者 {}
        if(param == undefined || param == ""){
            return {};
        } else {
            var strs = param.split('&');
            var arrObj = new Object();
            for(var i = 0, len = strs.length; i < len; i++){
                var tmp = strs[i].split('=');
                if (!(tmp[0] in arrObj)) {
                    arrObj[tmp[0]] = [];
                }
                arrObj[tmp[0]].push(tmp[1]);               
            }
            return arrObj;
        }
    }
}

dom节点查找

题目描述

查找两个节点的最近的一个共同父节点,可以包括节点自身。

输入描述:
oNode1 和 oNode2 在同一文档中,且不会为相同的节点
代码:
// 方法一
function commonParentNode(oNode1, oNode2) {
    while (oNode1) {
        if (oNode1.contains(oNode2)) {
            return oNode1;
        }
        oNode1 = oNode1.parentNode;
    }
}

// 方法二
function commonParentNode(oNode1, oNode2) {
    for (; oNode1; oNode1 = oNode1.parentNode) {
        if (oNode1.contains(oNode2)) {
            return oNode1;
        }
    }
}

根据包名,在指定空间中创建对象

题目描述(✨)

根据包名,在指定空间中创建对象

// 输入
namespace({a: {test: 1, b: 2}}, 'a.b.c.d')
// 输出
{a: {test: 1, b: {c: {d: {}}}}}
代码:
// 方法一
function namespace(oNamespace, sPackage) {
    var arr = sPackage.split('.');
    // 保留对原始对象的引用
    var res = oNamespace;
    for (var i = 0, len = arr.length; i < len; i++) {
        // 空间名在对象中
        if (arr[i] in oNamespace) {
            if (typeof oNamespace[arr[i]] !== "object") {
                // 将此属性设为空对象
                oNamespace[arr[i]] = {};
            }
        } else {
               // 空间名不在对象中,建立此空间名属性,赋值为空
                oNamespace[arr[i]] = {};
        }
        // 将指针指向下一个空间名属性
        oNamespace = oNamespace[arr[i]];
    }
    return res;
}

// 方法二
function namespace(oNamespace, sPackage) {
    sPackage.split('.').forEach((k) => {
        if (!oNamespace[k]) {
            oNamespace[k] = {};
        }
        oNamespace = oNamespace[k];
    });
}

数组去重

题目描述

为 Array 对象添加一个去除重复项的方法

// 输入
[false, true, undefined, null, NaN, 0, 1, {}, {}, 'a', 'a', NaN]

// 输出
[false, true, undefined, null, NaN, 0, 1, {}, {}, 'a']
代码:
// 方法一
Array.prototype.uniq = function () {
    return [...new Set(this)];
}

// 方法二
Array.prototype.uniq = function () {
    var arr = [];
    var flag = true;
    for (var i = 0; i < this.length; i++) {
        if (arr.indexOf(this[i]) == -1) {
            // 判断NaN
            if (this[i] != this[i] && typeof this[i] === 'number') {
                if (flag) {
                    arr.push(this[i]);
                    flag = false;
                }
            } else {
                arr.push(this[i]);
            }
        }
    }
    return arr;
}

斐波那契数列

题目描述

用 JavaScript 实现斐波那契数列函数,返回第n个斐波那契数。 f(1) = 1, f(2) = 1 等

function fibonacci(n) {
    if (n == 1 || n == 2) return 1;
    return fibonacci(n - 1) + fibonacci( n - 2);
}

时间格式化输出

题目描述(✨)

按所给的时间格式输出指定的时间
格式说明
对于 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 结果为 五

// 输入
(new Date(1409894060000), 'yyyy-MM-dd HH:mm:ss 星期w')
// 输出
2014-09-05 13:14:20 星期五
代码:
function formatDate(date, str) {
    var obj = {
        yyyy: date.getFullYear(),
        yy: ("" + date.getFullYear()).slice(-2),
        M: date.getMonth() + 1,
        MM: ("0" + (date.getMonth() + 1)).slice(-2),
        d: date.getDate(),
        dd: ("0" + date.getDate()).slice(-2),
        H: date.getHours(),
        HH: ("0" + date.getHours()).slice(-2),
        h: date.getHours() % 12,
        hh: ("0" + date.getHours() % 12).slice(-2),
        m: date.getMinutes(),
        mm: ("0" + date.getMinutes()).slice(-2),
        s: date.getSeconds(),
        ss: ("0" + date.getSeconds()).slice(-2),
        w: ['日', '一', '二', '三', '四', '五', '六'][date.getDay()]
    };
      // + 匹配任何包含至少一个 n 的字符串
    return str.replace(/[a-z]+/ig, function(v){return obj[v]});
}

获取字符串的长度

题目描述

如果第二个参数 bUnicode255For1 === true,则所有字符长度为 1,否则如果字符 Unicode 编码 > 255 则长度为 2

// 输入
'hello world, 牛客', false
// 输出
17
代码:
// 方法一
function strLength(s, bUnicode255For1) {
    if (bUnicode255For1) {
        return s.length;
    } else {
        let sum = 0;
        for (let i = 0; i < s.length; i++) {
            if (s.charCodeAt(i) > 255) {
                sum += 2;
            } else {
                sum += 1;
            }
        }
        return sum;
    }
}

// 方法一简化版
function strLength(s, bUnicode255For1) {
    let sum = 0;
    for (let i = 0; i < s.length; i++) {
        sum += (s.charCodeAt(i) > 255) ? 2 : 1;
    }
    return bUnicode255For1 ? s.length : sum;
}

邮箱字符串判断

题目描述

判断输入是否是正确的邮箱格式,返回布尔值

代码:
// 方法一
function isAvailableEmail(sEmail) {
    var reg = /^([A-z0-9_\-\.])+\@([A-z0-9_\-\.])+\.([A-z]{2,4})$/;
    return reg.test(sEmail);
}

// 方法二
function isAvailableEmail(sEmail) {
    var reg = /^([\w+\.])+@(\w+)([.]\w+)+$/;
    return reg.test(sEmail);
}

将字符串转化为驼峰格式

题目描述

css 中经常有类似 background-image 这种通过 - 连接的字符,通过 javascript 设置样式的时候需要将这种样式转换成 backgroundImage 驼峰格式,请完成此转换功能

  1. 以 - 为分隔符,将第二个起的非空单词首字母转为大写
  2. -webkit-border-image 转换后的结果为 webkitBorderImage
// 输入
'font-size'
// 输出
fontSize
代码:
function cssStyle2DomStyle(sName) {
    let str = sName.split('-');
    let arr = [];
    str.forEach((key,index) => {
        if (key != '') {
            arr.push(key);
        }
        for (let i = 1; i < arr.length; i++) {
            let char = arr[i].charAt(0).toUpperCase();
            arr[i] = char + arr[i].substring(1);
        }
    });
    return arr.join('');
}

字符串字符统计

题目描述

统计字符串中每个字符的出现频率,返回一个 Object,key 为统计字符,value 为出现频率

  1. 不限制 key 的顺序
  2. 输入的字符串参数不会为空
  3. 忽略空白字符
// 输入
'hello world'
// 输出
{h: 1, e: 1, l: 3, o: 2, w: 1, r: 1, d: 1}
代码:
// 方法一
function count(str) {
    var obj = {};
      // 代替空白字符
    str = str.replace(/\s+/g, '');
    for (var i = 0; i < str.length; i++) {
        if (obj[str[i]]) {
            obj[str[i]] += 1;
        } else {
            obj[str[i]] = 1;
        } 
    }
    return obj;
}

// 方法二
function count(str) {
    var obj = {};
    // 遍历非空白字符
    str.replace(/\S/g, function(str) {
        obj[str] ? obj[str] += 1 : obj[str] = 1;
    });
    return obj;
}

颜色字符串转换

题目描述(✨)

将 rgb 颜色字符串转换为十六进制的形式,如 rgb(255, 255, 255) 转为 #ffffff

  1. rgb 中每个 , 后面的空格数量不固定
  2. 十六进制表达式使用六位小写字母
  3. 如果输入不符合 rgb 格式,返回原始输入
// 输入
'rgb(255, 255, 255)'
// 输出
#ffffff
代码:
function rgb2hex(sRGB) {
   return sRGB.replace(/^rgb\((\d+)\s*\,\s*(\d+)\s*\,\s*(\d+)\)$/g, function(a, r, g, b){
       return '#' + hex(r) + hex(g) + hex(b);
   });
}
function hex(n){
    return n < 16 ? '0' + (+n).toString(16) : (+n).toString(16);
}

评论
评论
  目录