JS面试题

  • 解释jsonp原理,为何它不是真正的ajax?

    • 浏览器的同源策略(服务端没有同源策略)和跨域

    • 哪些html标签能绕过跨域?

    • jsonp原理

  • Document load 和ready的区别

  • == 和 === 的不同

  • 函数声明和函数表达式的区别?

    • 函数声明function fn(){...};
    • 函数表达式const fn = function (){...};
    • 函数声明会在代码执行前预加载,而函数表达式不会
  • new Object()和Object.create()的区别

    • {}等同于new Object(),原型Object.prototype
    • Object.create(null)没有原型
    • Object.create({...})可以指定原型
  • 关于this的场景

  • 关于作用域和自由变量的场景提-

  • 判断字符串以字母开头,后面字母数字下划线,长度6-3

  • 关于作用域和自由变量的场景提-2

    let a = 100;
    function test() {
      alert(a);
      a = 10;
      alert(a);
    }
    test();
    alert(a);
    
  • 手写字符串trim方法,保证浏览器兼容

  • 如何获取多个数字中的最大值

    function max() {
      const nums = Array.prototype.slice.call(arguments);
      let max = 0;
      nums.forEach(n=>{
        if (n>max){
          max = n;
        }
      });
      return max;
    }
    
  • 如何使用js实现继承?

    • class继承
    • prototype继承
  • 如何捕获JS程序中的异常

    try {
      //todo
    }catch (ex) {
      console.error(ex);//手动捕获catch
    }finally {
      //todo
    
    
  • 什么是json?

    • json是一种数据格式,本质是一段字符串

    • json格式和js对象结构一致,对js语言更友好

    • window.JSON是一个全局对象:JSON.stringify JSON.pars

  • 获取当前页面url参数

    • 传统方式,查找location.search

    • 新API,URLSearchParams

      // // 传统方式
      // function query(name) {
      //     const search = location.search.substr(1) // 类似 array.slice(1)
      //     // search: 'a=10&b=20&c=30'
      //     const reg = new RegExp(`(^|&)${name}=([^&]*)(&|$)`, 'i')
      //     const res = search.match(reg)
      //     if (res === null) {
      //         return null
      //     }
      //     return res[2]
      // }
      // query('d')
      
      // URLSearchParams
      function query(name) {
          const search = location.search//?后边的所有内容
          const p = new URLSearchParams(search)
          return p.get(name)
      }
      console.log( query('b') )
  • 手写数组flatern,考虑多层级

    function flat(arr) {
        // 验证 arr 中,还有没有深层数组 [1, 2, [3, 4]]
        const isDeep = arr.some(item => item instanceof Array)
        if (!isDeep) {
            return arr // 已经是 flatern [1, 2, 3, 4]
        }
    
        const res = Array.prototype.concat.apply([], arr)
        return flat(res) // 递归
    }
    
    const res = flat( [1, 2, [3, 4, [10, 20, [100, 200]]], 5] )
    console.log(res)
    
    
  • 数组去重

    • 传统方式,遍历元素挨个比较,去重

    • 使用set

    • 考虑计算效率

      // // 传统方式
      // function unique(arr) {
      //     const res = []
      //     arr.forEach(item => {
      //         if (res.indexOf(item) < 0) {
      //             res.push(item)
      //         }
      //     })
      //     return res
      // }
      
      // 使用 Set (无序,不能重复)
      function unique(arr) {
          const set = new Set(arr)
          return [...set]
      }
      
      const res = unique([30, 10, 20, 30, 40, 10])
      console.log(res)
      
      
  • 手写深拷贝

  • 介绍一下RAF requestAnimateFrame

    • 要想动画流畅,更新频率要60帧/s,即16.67ms更新一次视图

    • setTimeout 要手动控制频率,而RAF浏览器会自动控制

    • 后台标签或隐藏iframe中,RAF会暂停,而setTimeout依然执行

      // 3s 把宽度从 100px 变为 640px ,即增加 540px
      // 60帧/s ,3s 180 帧 ,每次变化 3px
      
      const $div1 = $('#div1')
      let curWidth = 100
      const maxWidth = 640
      
      // // setTimeout
      // function animate() {
      //     curWidth = curWidth + 3
      //     $div1.css('width', curWidth)
      //     if (curWidth < maxWidth) {
      //         setTimeout(animate, 16.7) // 自己控制时间
      //     }
      // }
      // animate()
      
      // RAF
      function animate() {
          curWidth = curWidth + 3
          $div1.css('width', curWidth)
          if (curWidth < maxWidth) {
              window.requestAnimationFrame(animate) // 时间不用自己控制
          }
      }
      animate()
      
  • 前端性能如何优化?一般从哪几方面考虑?

    • 原则:多使用内存,缓存,减少计算,减少网络请求
    • 方向:加载页面,页面渲染,页面操作流畅度