• 腾讯前端高频手写面试题


    转化为驼峰命名

    var s1 = "get-element-by-id"
    
    // 转化为 getElementById
    
    var f = function(s) {
       
        return s.replace(/-\w/g, function(x) {
       
            return x.slice(1).toUpperCase();
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    实现一个call

    call做了什么:

    • 将函数设为对象的属性
    • 执行&删除这个函数
    • 指定this到函数并传入给定参数执行函数
    • 如果不传入参数,默认指向为 window
    // 模拟 call bar.mycall(null);
    //实现一个call方法:
    Function.prototype.myCall = function(context) {
       
      //此处没有考虑context非object情况
      context.fn = this;
      let args = [];
      for (let i = 1, len = arguments.length; i < len; i++) {
       
        args.push(arguments[i]);
      }
      context.fn(...args);
      let result = context.fn(...args);
      delete context.fn;
      return result;
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    解析 URL Params 为对象

    let url = 'http://www.domain.com/?user=anonymous&id=123&id=456&city=%E5%8C%97%E4%BA%AC&enabled';
    parseParam(url)
    /* 结果
    {
        user: 'anonymous',
      id: [ 123, 456 ], // 重复出现的 key 要组装成数组,能被转成数字的就转成数字类型
      city: '北京', // 中文需解码
      enabled: true, // 未指定值得 key 约定为 true
    }
    */
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    function parseParam(url) {
       
      const paramsStr = /.+\?(.+)$/.exec(url)[1]; // 将 ? 后面的字符串取出来
      const paramsArr = paramsStr.split('&'); // 将字符串以 & 分割后存到数组中
      let paramsObj = {
       };
      // 将 params 存到对象中
      paramsArr.forEach(param => {
       
        if (/=/.test(param)) {
        // 处理有 value 的参数
          let [key, val] = param.split('='); // 分割 key 和 value
          val = decodeURIComponent(val); // 解码
          val = /^\d+$/.test(val) ? parseFloat(val) : val; // 判断是否转为数字
    
          if (paramsObj.hasOwnProperty(key)) {
        // 如果对象有 key,则添加一个值
            paramsObj[key] = [].concat(paramsObj[key], val);
          } else {
        // 如果对象没有这个 key,创建 key 并设置值
            paramsObj[key] = val;
          }
        } else {
        // 处理没有 value 的参数
          paramsObj[param] = true;
        }
      })
    
      return paramsObj;
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    Object.is

    Object.is解决的主要是这两个问题:

    +0 === -0  // true
    NaN === NaN // false
    
    
    • 1
    • 2
    • 3
    const is= (x, y) => {
       
      if (x === y) {
       
        // +0和-0应该不相等
        return x !== 0 || y !== 0 || 1/x === 1/y;
      } else {
       
        return x !== x && y !== y;
      }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    参考:前端手写面试题详细解答

    手写 Promise

    const PENDING = "pending";
    const RESOLVED = "resolved";
    const REJECTED = "rejected";
    
    function MyPromise(fn) {
       
      // 保存初始化状态
      var self = this;
    
      // 初始化状态
      this.state = PENDING;
    
      // 用于保存 resolve 或者 rejected 传入的值
      this.value = null;
    
      // 用于保存 resolve 的回调函数
      this.resolvedCallbacks = [];
    
      // 用于保存 reject 的回调函数
      this.rejectedCallbacks = [];
    
      // 状态转变为 resolved 方法
      function resolve(value) {
       
        // 判断传入元素是否为 Promise 值,如果是,则状态改变必须等待前一个状态改变后再进行改变
        if (value instanceof MyPromise) {
       
          return value.then(resolve, reject);
        }
    
        // 保证代码的执行顺序为本轮事件循环的末尾
        setTimeout(() => {
       
          // 只有状态为 pending 时才能转变,
          if (self.state === PENDING) {
       
            // 修改状态
            self.state = RESOLVED;
    
            // 设置传入的值
            self.value = value;
    
            // 执行回调函数
            self.resolvedCallbacks.forEach(callback => {
       
              callback(value);
            });
          }
        }, 0);
      }
    
      // 状态转变为 rejected 方法
      function reject(value) {
       
        // 保证代码的执行顺序为本轮事件循环的末尾
        setTimeout(() => {
       
          // 只有状态为 pending 时才能转变
          if (self.state === PENDING) {
       
            // 修改状态
            self.state = REJECTED;
    
            // 设置传入的值
            self.value = value;
    
            // 执行回调函数
            self.rejectedCallbacks
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
  • 相关阅读:
    『computed 不生效的坑』
    安卓应用自动化测试工具Appium实操分享
    TS 的 高级用法 与 知识点总结
    C语言中,字节对齐是一种重要的内存管理概念
    哪些人需要考PMP®证书呢?考了PMP®证书有什么用呢?
    TOUGH2系列建模方法及在CO2地质封存、水文地球化学、地热、地下水污染等领域中的技术
    什么是CMDB?为什么企业需要CMDB?
    ​HTTP/2 和 Websocket​
    PPT中的文字跟随Excel动态变化,且保留文字格式
    (Java高级教程)第三章Java网络编程-第七节2:Servlet API和综合案例
  • 原文地址:https://blog.csdn.net/helloworld1024fd/article/details/127859525