面试小结(附部分答案)

111 阅读5分钟

前言

准备换工作了,毕业以来一直在一家中小型企业写了一年多的React,现在无论是状态还是学习的动力都不是最巅峰的时候,是时候准备开启新的篇章了

面试

项目相关

首先是常规的自我介绍,接下来就是聊项目,这边印象比较深的是聊到了一个性能优化的场景

我的回答是:

观察到页面比较卡顿,然后使用Chrome的火焰图定位到了是用于处理图表数据到两个方法出现了性能问题,之后具体的优化方法是:处理X轴的方法中改用了Set集合来存取,处理Y轴数据的方法减少里面的for循环,降低时间复杂度来达到优化的效果

答的不好,听到后面面试官还问了几个相关的问题,我归纳了一下,觉得可以这样回答:

首先这是一个表格模块,里面有一列使用的是Echarts图表来展示数据,表格采用滚动分页,每页请求10条表格数据,其中每个图表数据平均是5万条左右。当时观察到这个页面会比较卡顿,于是使用Chrome火焰图 去分析了一下这个模块的事件循环大概的执行时间,发现了一个长任务,点击这个任务的调用树去定位到了一个副作用里面的两个处理数据的方法执行时间非常长,于是就针对这两个方法进行了一个优化。

首先是X轴数据的处理方法,它的功能主要是从原始数据里面获取日期数据,原本用的是数组,最后给它改为Set结构,Set底层的实现会相对纯粹一些,性能较好。Y轴数据处理的方法是用于补全数据的,里面的循环比较多,这边着手的重点就是减少里面的循环时间,降低时间复杂度

最后还对这个图表组件进行了懒加载处理

这是当时进行性能处理的方案,如果是现在去处理的话,应该还有更多的优化空间,例如开启多线程渲染,例如利用事件循环机制中的requestAnimationFrame或者requestIdentCallback来调度任务的执行

JavaScript基础题

高阶函数

  • 高阶函数是指至少满足下列条件之一的函数:
    • 可以被当做参数传递
    • 可以被当做返回值输出

应用:

  • 作为回调函数
  • 闭包
  • 防抖
  • 节流
  • 柯里化
  • 去柯里化
  • 偏函数
  • Trunk函数
  • ...

let和const的区别

  • let和const都能形成块作用域
  • const声明时必须初始化变量的值,let则不用
  • let声明的变量时可以改变的,const声明的基础数据类型不可改变,引用数据类型引用地址不可变,里面的值时可以变的

箭头函数和普通函数的区别

  • 普通函数可以用作构造函数,被new实例化,箭头函数则不可以

  • 普通函数的this是动态变化的,箭头函数的this在声明会跟着上下文的this,并且不可被call,apply,bind这些方法所改变

深拷贝和浅拷贝

  • 浅拷贝和深拷贝只针对引用数据类型

  • 如果引用数据类型的属性时基本类型,那拷贝的就是基本类型的值,如果是引用类型,拷贝的就是内存地址,即浅拷贝只拷贝一层,深层次的引用类型则共享内存地址

  • 深拷贝就是层层拷贝,会开辟一个新的内存空间,将数据中属性全部都拷贝一遍

实现浅拷贝的方法:

  • Object.assign
  • slice()
  • concat()
  • 拓展运算符

实现深拷贝的方法:

  • JSON.stringify()
    • 弊端:会忽略undefinedsymbol函数
  • _.cloneDeep()
  • jquery.extend()
  • 手写循环递归
function deepClone(obj, hash = new WeakMap()) {
    if(obj === null || obj === undefined) return obj;
    if(obj instanceof Date) return new Date(obj);
    if(obj instanceof RegExp) return new RegExp(obj);
    
    // 可能是普通的值或者函数
    if(typeof obj !== 'object') return obj;
    // 是对象的话就要进行深拷贝
    if(hash.get(obj)) return hash.get(obj);
    let cloneObj = new obj.constructor();
    
    hash.set(obj, cloneObj);
    for(let key in obj) {
      if(obj.hasOwnProperty(key)){
        // 循环递归
        cloneObj[key] = deepClone(obj[key], hash);
      }
    }
    return cloneObj;
}

LocalStorage、SessionStorage和cookie的区别

  • 存储大小:cookie数据大小不能超过4ksessionStoragelocalStorage虽然也有存储大小的限制,但比cookie大得多,可以达到5M左右

  • 有效时间:localStorage存储持久数据,浏览器关闭后数据不会丢失,除非你主动去删除数据;sessionStorage数据在当前浏览器窗口关闭后自动删除;cookie设置的cookie过期时间之前一直有效

  • 数据与服务之间的交互方式,cookie的数据会自动传递到服务器,服务端也可以写cookie到客户端;sessionStoragelocalStorage不会自动把数据发给服务器,仅存在本地

map和forEach的区别

map遍历数组,然后将数组里面的数据通过一定的操作再返回,会形成一个新数组,forEach就是单纯的遍历数组方法,且遍历时不能被break,continue等中断。

事件流

标准事件流分为了三个阶段,事件捕获,目标阶段和事件冒泡阶段

  • 阻止事件冒泡:event.stoppropagation(),Vue可以用.stop事件修饰符

Vue面试题

  • Vue生命周期有哪些
  • NextTick
  • Vue响应式的原理
  • $set是用来干嘛的
  • Router有哪些模式,传参方式都有哪些,如何设置参数
  • 介绍一下VueX
  • key的作用
  • computed和watch的区别

总结

整体来说这次的面试准备的不是很充足,还有很多可以改进的地方,很多基础问题答的不是很好,继续改进吧