首页前端开发Node.js牛客网JS必刷题 01-10

牛客网JS必刷题 01-10

时间2023-11-27 17:34:03发布访客分类Node.js浏览559
导读:1. 修改this指向封装函数 f,使 f 的 this 指向指定的对象。这里给出三种写法,哪种都可以。// apply修改this作用域 function bindThis(f, oTarget { return functio...

1. 修改this指向

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

这里给出三种写法,哪种都可以。

// apply修改this作用域
function bindThis(f, oTarget) {

    return function () {

        return f.apply(oTarget,arguments)
    }

}


// call修改this作用域
function bindThis(f, oTarget) {

    return function (){

        return f.call(oTarget,...arguments)
    }

}


// bind修改this作用域
function bindThis(f, oTarget) {

    return function (){

        return f.bind(oTarget,...arguments)() // 手动调用
    }

}
    

相关知识点:

  1. apply、call、bind区别

apply、call、bind的作用都是修改执行上下文 apply、call都是返回函数立即执行的u> 结果/u> ,其中apply第二个参数之后是数组Array,call第二个参数之后是逐个参数。 bind返回的是函数,需要手动执行结果。第二个参数之后是逐个参数。

2. 获取url参数

获取 url 中的参数

指定参数名称,返回该参数的值 或者 空字符串 不指定参数名称,返回全部的参数对象 或者 { } 如果存在多个同名参数,则返回数组

输入:http://www.nowcoder.com?key=1& key=2& key=3& test=4#hehe key

输出:1, 2, 3

function getUrlParam(sUrl, sKey) {

        let newArr = []
        let newObj = {
}

        // 获取?号后面#号前面的值
        let query = sUrl.split('#')[0].split('?')[1]
        // 如果query存在
        if (query) {
    
          let arr = query.split('&
    ')
          for(let i = 0 ;
     i  arr.length;
 i++) {

            if (arr[i]) {

              arr[i] = arr[i].split('=')
              // 数组
              if (sKey !== undefined) {

                if(arr[i][0] === sKey) {

                  newArr.push(arr[i][1])
                }

              // 对象
              }
 else {

                if(arr[i][0] in newObj) {

                  newObj[arr[i][0]].push(arr[i][1])
                }
 else {

                  newObj[arr[i][0]] = [arr[i][1]]
                }

              }

            }

          }

          // 判断sKey有没有值
          if(sKey !== undefined) {

            switch(newArr.length) {
    
              case 0 : return '';
    break;
    
              case 1 : return newArr[0];
     break;
    
              default: return newArr;
    break;

            }

          }
 else {

            return newObj
          }

        // 如果query不存在,判断sKey是否存在,如果存在就返回空对象,如果不存在就返回空字符串
        }
 else {

          return sKey !== undefined ? '' : {
}

        }

      }
    

相关知识点:

  • url的组成部分

https://user:pass@www.baidu.com:80/index.html?type=1& name=2#haha http/https 是协议 user:pass@ 是登录认证 www.baidu.com 是域名,服务器地址 :80 是端口号 /index.html 是请求资源文件路径 ?type=1& name=2 是查询字符串,携带参数,给服务器传的内容。 #haha 是哈希,片段标识符

  • split方法

字符串分割成数组的方法,里面的参数是以什么分割,如果不传就是空字符串为分割,返回值是一个数组。

  • query部分可以使用正则

3. dom节点查找

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

输入描述: oNode1 和 oNode2 在同一文档中,且不会为相同的节点

function commonParentNode(oNode1, oNode2) {

    if(oNode1.contains(oNode2)) {

        return oNode1
    }
 else {

        // 一直将node1向上升
        return commonParentNode(oNode1.parentNode,oNode2)
    }

}

相关知识点:

  • contains API

查看dom元素包含关系,包含返回true,不包含返回false 参考MDN

  • 递归(参考数据结构树)

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

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

function namespace(oNamespace, sPackage) {
    
    let scope = sPackage.split('.')
    let ns = oNamespace
    for(let i = 0;
     i scope.length;
 i++) {

        // 如果对象中没有该元素,或者不是对象,那么就置为空对象
       if(!ns.hasOwnProperty(scope[i]) || Object.prototype.toString.call(ns[scope[i]]) !== '[object Object]') {

            ns[scope[i]] = {
}

        }

        // 然后继续往下找
        ns = ns[scope[i]]
    }

    return oNamespace
}

考察知识点:

  • 判断对象的自身是否有某属性(hasOwnProperty)
  • hasOwnProperty / typeof / in / instanceof 的区别

hasOwnProperty 是判断对象自身有没有某属性,不包含原型链的方法。 in 是判断对象在自身和原型链上有没有该方法。 instanceof 是判断对象在原型链上有没有该方法。 typeof 判断操作数的类型,但是null也会判断为"object"

  • 准确判断某值的类型

Object.prototype.toString.call(123) \=== "object Number" Object.prototype.toString.call('aaa') \=== "object String" Object.prototype.toString.call(true) \=== "object Boolean" Object.prototype.toString.call(undefined) \=== "object Undefined" Object.prototype.toString.call(null) \=== 'object Null' Object.prototype.toString.call({ } ) \=== 'object Object' Object.prototype.toString.call([]) \=== 'object Array' Object.prototype.toString.call(Math) \=== "object Math" Object.prototype.toString.call(new Date()) \=== "object Date" Object.prototype.toString.call(new RegExp) \=== "object RegExp"

  • 递归(对象的嵌套参考数据结构中的树)

5. 数组去重

为 Array 对象添加一个去除重复项的方法 输入 false, true, undefined, null, NaN, 0, 1, { } , { } , 'a', 'a', NaN 输出 false, true, undefined, null, NaN, 0, 1, { } , { } , 'a'

u> 这个题,狗就狗在,还有NaN/u>

// 方法一:终极思路
Array.prototype.uniq = function () {

    return [...new Set(this)]
}


// 方法二:includes避免NaN的问题
Array.prototype.uniq = function () {
    
    const arr = [];
    
    this.forEach((val, index) =>
 {

        if (!arr.includes(val)) {

            arr.push(val)
        }

    }
    )
    return arr;

}


// 方法三:使用reduce+includes
Array.prototype.uniq = function () {
    
    return this.reduce((prev, val) =>
 {

        if (!prev.includes(val)) {

            prev.push(val)
        }

        return prev
    }
, [])
}


// 方法四:普通思路,遍历之后比较值
Array.prototype.uniq = function () {
    
    let arr = []
    let flag = true
    this.forEach(value =>
 {

        // == -1 有两种情况,一种是NaN,一种是有相同值
        if(arr.indexOf(value) === -1) {

            // 如果是NaN
            if(value !== value) {

                // flag是标记,第一个NaN就进,之后的就不进去
                if(flag){

                  arr.push(value)  
                  flag = false
                }

            }
 else {

                arr.push(value)  
            }

        }

    }
)
    return arr
}
    

相关知识点:

  • uniq方法中的this指向哪里?

Array构造函数的原型方法中的this指的是数组实例。

  • Set的特性

Set存储的成员是唯一的,不是重复的,如果有重复会自动过滤掉. ES6(七)—— Set & Map

  • (NaN === NaN) => false

NaN : is not a number,不等于自己 typeof NaN => number Object.prototype.toString.call(NaN) => "object Number" ES6 新增方法:Number.isNaN() 用来判断是否属于数字

6. 斐波那契数列

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

斐波那契数列基本学js都会,1 1 2 3 5 8 13,后一个是前两个的和。

// 方法一:递归思路
function fibonacci(n) {

    if(n === 0) return 0
    if(n === 1 || n === 2) return 1
    return fibonacci(n-1) + fibonacci(n-2)
}


// 方法二:迭代思路
function fibonacci(n) {
    
    let num1 = 1
    let num2 = 1
    let sum = 0
    for(let i = 3;
     i = n;
 i++) {

        sum = num1 + num2
        num1 = num2
        num2 = sum
    }

    return sum
}


// 上面写法可以过oj,但是如果数字大点就超级慢,使用缓存很可
// 方法三:递归优化思路
function fibonacci(n,cache = {
}
) {

    // 有缓存就直接读缓存
    if(n in cache) return cache[n]
    if(n === 1 || n === 2) {

        cache[n] = 1
        return 1
    }

    // 没有缓存算完之后存入缓存
    let temp = fibonacci(n-1, cache) + fibonacci(n-2,cache)
    cache[n] = temp
    return temp
}

相关知识点:

  • 递归

7. 时间格式化输出

题目描述 按所给的时间格式输出指定的时间 格式说明 对于 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) {

    let year = ''+t.getFullYear()
    let month = t.getMonth() + 1
    let day = t.getDate()
    let hour = t.getHours()
    let minutes = t.getMinutes()
    let second = t.getSeconds()
    let week = ['日','一','二','三','四','五','六']
    let date = {

      'yyyy': year,
      'yy': year.slice(2),
      'MM': ten(month),
      'M': month,
      'dd': ten(day),
      'd': day,
      'HH': ten(hour),
      'H': hour,
      'hh': ten(hour % 12),
      'h': hour % 12,
      'mm': ten(minutes),
      'm': minutes,
      'ss': ten(second),
      's': second,
      'w': week[t.getDay()]
    }

    for(let key in date) {
 
      str = str.replace(key,date[key])
    }

    return str
  }
    

  // 不足10的前面要加0
  const ten = num  =>
     num >
    = 10 ? num : '0' + num

考察知识点:

  • 获取年月日周时分秒的系统API
  • 格式统一处理
  • 字符串替换 (replace)

8. 获取字符串的长度

题目描述 如果第二个参数 bUnicode255For1 === true,则所有字符长度为 1 否则如果字符 Unicode 编码 > 255 则长度为 2 输入 hello world, 牛客', false 输出 17

function strLength(s, bUnicode255For1) {
    
    if(bUnicode255For1) return s.length;
    
    let len = s.length
    for(let i = 0;
     i  s.length;
 i++) {
    
        if(s[i].charCodeAt() >
 255) len++
    }

    return len
}
    

相关知识点:

  • 获取字符的 Unicode 编码 API —— u> str.charCodeAt()/u>

9. 邮箱字符串判断

题目描述 判断输入是否是正确的邮箱格式

考察正则的一道题目,方法也是多种多样,这里只有一种简单的参考。

// ^ 表示开头
// [] 表示匹配字符的范围
// \w 表示正常符号 [0-9a-zA-Z_]
// \. 是对任意符.进行转义,表示字符.
// + 表示前面的表达式,一次到多次
function isAvailableEmail(sEmail) {

    return /^[\w\.]+@\w+\.\w+/.test(sEmail)
}

相关知识点:

  • 邮箱格式
  • 正则表达式的规则和匹配

10. 颜色字符串转换

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

rgb 中每个 , 后面的空格数量不固定 十六进制表达式使用六位小写字母 如果输入不符合 rgb 格式,返回原始输入

输入 :'rgb(255, 255, 255)' 输出 :#ffffff

function rgb2hex(sRGB) {
    
    // 正则匹配获取!!三个数值,\d填充
    let reg = sRGB.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)/)
    if(!reg) return sRGB;
    
    // 字符串拼接
    let str = '#'
    for(let i = 1;
     i  reg.length;
 i++) {
    
      // 将字符串转成数字
      let m = parseInt(reg[i])
      if (m >
    = 0 &
    &
 m = 255) {
    
        // 然后转化成16进制
        str += (m >
= 16 ? m.toString(16) : '0' + m.toString(16))
      }
 else {

        return sRGB
      }

    }

    return str
  }
    

相关知识点:

  • toString的进制转换

颜色是16进制,所以toString(16)可以得到结果

  • 字符串中如何截取数字(不限于正则) match

注意:一定要理解之后去程序里面运行一遍。

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!


若转载请注明出处: 牛客网JS必刷题 01-10
本文地址: https://pptw.com/jishu/557857.html
node版本管理神器nvm安装使用教程(Windows11版本) 如何使用npm创建Node.js项目?

游客 回复需填写必要信息