js常见题目汇总

1、查找两个节点的最近的一个共同父节点,可以包括节点自身
实现方法一:用递归

function commonParentNode(oNode1, oNode2) {
    if(oNode1.contains(oNode2)){
        return oNode1
    }else{
        return commonParentNode(oNode1.parentNode,oNode2)
    }
}

这里不用加节点二是否又包含节点一这个判断条件,因为在上面的判断中如果不成立,就会一直向上查,一层一层递归,总会找到那个父节点的
实现方法二:

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

随便找一个节点,通过循环一直往上查就好了

2、为 Array 对象添加一个去除重复项的方法
例如:输入为[false, true, undefined, null, NaN, 0, 1, {}, {}, ‘a’, ‘a’, NaN]
则输出为:[false, true, undefined, null, NaN, 0, 1, {}, {}, ‘a’]

方法一:思路是首先声明一个数组,循环原数组,将每一项与新数组的值比较,看新数组里面是否已经存在当前值,若已经存在,不进行push操作,若不存在将它push进新数组,NaN是一个特殊情况,事先声明一个变量flag,控制NaN只能一次进入push操作的判断


    Array.prototype.uniq = function () {
        var res=[];//这个数组的作用是将原数组中的值依次往里加,第一个判断是当数组里面已经有当前循环到的这一项了,那么就不加
        var flag=true;
        for(var i=0;i<this.length;i++){
            if(res.indexOf(this[i])==-1){//如果当前这一项在res数组里面不存在,就将它push
                if(this[i]!=this[i]){//为NaN时
                    if(flag){//只有第一个NaN能进这个判断条件
                        res.push(this[i]);
                        flag=false;
                    }
                }else{
                    res.push(this[i])
                }
            }
        }
        return res
    }

方法二:使用es6

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

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

方法一:使用数组返回

function fibonacci(n) {
    var res=[];
    if(n==1){
        return 1
    }
    if(n==2){
        return 1
    }
    res[1]=1;
    res[2]=1;
    for(var i=3;i<=n;i++){
        res[i]=res[i-1]+res[i-2]
    }
    return res[n]
}

方法二:使用递归(算法时间复杂度较高)

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

4、统计字符串中每个字符的出现频率,返回一个 Object,key 为统计字符,value 为出现频率
(1) 不限制 key 的顺序
(2) 输入的字符串参数不会为空
(3) 忽略空白字符

function count(str) {
    var obj={};
    for(var i=0;i<str.length;i++){
        if(str[i]!=' '){//字符不为空时
            obj[str[i]]=obj[str[i]]?++obj[str[i]]:1//对象里面的属性名称为str[i],value初始值为1为,后面出现过了就递增,所以判断条件为obj[str[i]]是否存在
        }
    }
    return obj
}

5、css 中经常有类似 background-image 这种通过 - 连接的字符,通过 javascript 设置样式的时候需要将这种样式转换成 backgroundImage 驼峰格式,请完成此转换功能
(1) 以 - 为分隔符,将第二个起的非空单词首字母转为大写
(2)-webkit-border-image 转换后的结果为 webkitBorderImage

思路是首先将字符串分割为字符串数组,如果数组第一项为空,那么代表字符串开头是‘-’,所以重新分割字符串数组,从第二个字符开始,
将数组索引为1后开始的每一项首字母大写,最后将它们拼接成一个完整的字符串

function cssStyle2DomStyle(sName) {
  var arr=sName.split('-');
    if(arr[0]==''){
        arr=sName.slice(1).split('-');
    }
    for(var i=1;i<arr.length;i++){
        arr[i]=arr[i].charAt(0).toUpperCase()+arr[i].slice(1)
    }
    var s='';
    for(var i=0;i<arr.length;i++){
        s+=arr[i];
    }
    return s
}

6、将 rgb 颜色字符串转换为十六进制的形式,如 rgb(255, 255, 255) 转为 #ffffff
(1) rgb 中每个 , 后面的空格数量不固定
(2)十六进制表达式使用六位小写字母
(3)如果输入不符合 rgb 格式,返回原始输入

方法一:match方法,match方法可在字符串内查找一个或多个与指定正则表达式匹配的子字符串。详细请参照http://www.softwhy.com/article-8668-1.html(蚂蚁部落)

方法的返回值是存放着匹配结果的数组,但数组元素并不一定全都是匹配结果

function rgb2hex(sRGB) {
    var regexp=/rgb\((\d+),\s*(\d+),\s*(\d+)\)/;
    var ret=sRGB.match(regexp);
    if(!ret){
        return sRGB;
    }else{
        var str='#';
        for(var i=1;i<=3;i++){
            var m=parseInt(ret[i]);
            if(m<=255&&m>=0){
                str+=(m<16?'0'+m.toString(16):m.toString(16));
            }else{
                return sRGB;
            }
        }
        return str;
    }
}

方法二:replace方法的第一个参数是正则表达式,第二个参数如果是一个函数的情况下,在只有一个匹配项(即与模式匹配的字符串)的情况下,会向这个函数传递3个参数:模式的匹配项、模式匹配项在字符串中的位置和原始字符串。在正则表达式中定义了多个捕获组的情况下,传递给函数的参数依次是模式的匹配项、第一个捕获组的匹配项、第二个捕获组的匹配项…,但最后两个参数仍然分别是模式的匹配项在字符串中的位置和原始字符串。
例如在下面这个函数的replace方法中第二个参数为函数,它里面的a就是整个模式的匹配项,r就是第一个捕获组的匹配项,以此类推…(捕获组就是用括号包起来的比如(\d+)就是一个组

function rgb2hex(sRGB) {
    var reg=/\^rgb\((\d+)\,\s*(\d+)\s*\,\s*(\d+)\)$/g;
    if(!reg.test(sRGB)){
        return sRGB
    }else{
        return sRGB.replace(/\^rgb\((\d+)\,\s*(\d+)\s*\,\s*(\d+)\)$/g,function (a,r,g,b){
                     return '#'+hex(r)+hex(g)+hex(b)
                })
    }
    function hex(n){
        var n=parseInt(n);
        if(n<=255&&n>=0){
            return n<16?'0'+(+n).toString(16):(+n).toString(16)
        }else{
            return sRGB
        }
    }
}

7、判断输入是否是正确的邮箱格式
ps(下面的正则表达式还是有点懵)
详情参考 http://www.softwhy.com/article-8987-1.html

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

8、按所给的时间格式输出指定的时间
格式说明
对于 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(t,str){
  var obj = {
    yyyy:t.getFullYear(),//获取年份,例如2019
    yy:(""+ t.getFullYear()).slice(-2),//只要后两位19,slice(-2)==slice(length-2),也就是4-2
    M:t.getMonth()+1,//这个直接获取到的是0~11,所以要加1
    MM:("0"+ (t.getMonth()+1)).slice(-2),//加1之后的值拼接上0之后可能为3位,那么截取之后是3-2=1,从索引为1开始包括1,就刚好是两个长度的月份,如果拼接之后是2位,2-2=0,从索引为0开始包括0,也刚好补齐两位长度的月份,后面的情况也是一样
    d:t.getDate(),//获取到多少号
    dd:("0" + t.getDate()).slice(-2),
    H:t.getHours(),//24小时制,直接可以获取
    HH:("0" + t.getHours()).slice(-2),
    h:t.getHours() % 12,//12小时制,需要处理一下
    hh:("0"+t.getHours() % 12).slice(-2),
    m:t.getMinutes(),
    mm:("0" + t.getMinutes()).slice(-2),
    s:t.getSeconds(),
    ss:("0" + t.getSeconds()).slice(-2),
    w:['日', '一', '二', '三', '四', '五', '六'][t.getDay()]//返回的是0~6,0就是周日
  };
  return str.replace(/([a-z]+)/ig,function($1){return obj[$1]});
}

分析:上面代码中的+1 slice(-2)解释如下:
加1之后的值拼接上0之后可能为3位,那么截取之后是3-2=1,从索引为1开始包括1,就刚好是两个长度的月份,如果拼接之后是2位,2-2=0,从索引为0开始包括0,也刚好补齐两位长度的月份,后面的情况也是一样

敲重点:关于replace方法的第二个参数是函数的情况,我想说的是:
replace()函数的第一个参数是正则表达式,并且执行的是全局匹配,那么第二个函数参数会多次被调用
详情请参考:https://www.cnblogs.com/lvmylife/p/9079297.html

9、拉齐有一个01序列,他可以对这个序列进行任意多次变换,每次变换都是把序列的最后若干个元素放到最前面,例如:010011,将最后3个元素011放到最前面,序列变为011010。所有变换结束后,拉齐需要挑出一个全为1的连续区间,要求最大化区间长度。

最重要的思路就是将字符串首尾相连,然后遍历出连1长度最长的一截

function judge(str) {
            if(str.indexOf('0') < 0) {
                return str.length;
            } else if(str.indexOf('1') < 0) {
                return 0
            } else {
                let judgeStr = str + str;
                let arr = judgeStr.match(/1{1,}/g);//返回的是所有匹配到的连1的数组
                let result = arr.reduce((total, num) => {
                    let result = total > num ? total : num;//选出最大的一个,下一次循环进来的total就是上一次循环返回的结果result
                    return result;
                })
                return result.length;
            }
        };
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值