社招一年多前端微信面经(挂)

3,120 阅读10分钟

前言

文章开始之前,先介绍下个人背景,18年普通本科信管专业毕业,到写文章时有一年多经验,主要使用的是vue。

年前本来不打算面试的,才刚开始复习(这个年限的hc比较少),但是恰好遇到腾讯大佬在招人,便试着投了简历,大概3天后收到了面试短信。

面试的部门是微信支付基础架构部,早前就听说微信面试难度很大,轮次很多,但是心里一直有个大厂梦,这次机会不想错过。 跟面试官约的是晚上,恰逢跨年夜。

下班就到了滨海大厦,腾讯的前台小姐姐很好看呀,长相姣好,妆容精致,身高170+。

咳咳,扯远了,开始正题吧

一面(1h,过)

一面出了5道笔试题

实现斐波那契数列

我用的是最简单的递归方法实现的,果不其然,面试官问我怎么进行优化

function Fibo(n){
    if(n<=0){
        return 0
    }
    if(n===1){
        return 1
    }
    return Fibo(n-1)+Fibo(n-2)
}

非递归循环实现:

function Fibo(n) {
  if (n <= 0) {
    return 0
  }
  if(n == 1) {
    return 1
  };
  let fn_2 = 0
  let fn_1 = 1
  let fn = 0;
  for (let i = 2; i <= n; i++) {
    fn = fn_1 + fn_2
    fn_2 = fn_1
    fn_1 = fn
  }
  return fn
}

手写冒泡排序

function bubbleSort(arr){
    if(!arr.length){
        return arr
    }
    for(let i=0,l=arr.length;i<l-1;i++){
        for(let j=1;j<l-1-i;j++){
            if(arr[j]>arr[j+1]){
                let temp
                temp=arr[j+1]
                arr[j]=temp
                arr[j+1]=arr[j]
            }
        }
    }
    return arr
}

实现的是升序还是降序? 升序

怎么实现降序? 将内层循环的if条件语句改为小于号即可

时间复杂度是多少,这个很简单,O(n^2)

手写二叉树的中序遍历

function inOrder(root,arr=[]){
    if(root){
        inOrder(root.left,arr)
        arr.push(root.val)
        inOrder(root.right,arr)
    }
    return arr
}

使用的递归的方式解决,其实还可以考虑非递归的方式,网上有很多实现,不再赘述

判断一个点是否在圆内

直接套用数学公式

function inCircle(cx,cy,x,y,r){
    return (cx-x)^2+(cy-y)^2<r^2
}

其中(cx,cy)是点坐标,(x,y)为圆心,r为半径

为什么不用开根号? 巴拉巴拉

实现_.[2,3,4].increase(1).reverse().val()

用原型链继承即可实现,就不列代码了

自我介绍和项目介绍

每个人针对自己的情况介绍,注意介绍的项目一定要非常熟悉,面试官会往死里问的

简历上写了英语听说读写流利,面试官让我来一段英文自我介绍,这个是我的强项

二分查找,时间复杂度和空间复杂度

function binarySearch(arr,val){
    if(!arr.length){
        return -1
    }
    let low=0,high=arr.length-1
    while(low<=high){
        let mid=Math.floor((low+high)/2)
        for(let i=0;i<arr.length;i++){
            if(arr[i]===val){
                return i
            }
            else if(arr[i]>val){
                high=mid-1
            }
            else{
                low=mid+1
            }
        }
    }
}

复杂度是O(nlogn)

绝对定位和相对定位

送分题

/*
** position:relative 相对定位,相对自身定位
** position:absolute 绝对定位,相对于最近的不为static的父级元素定位
*/

vue v-for里的key作用

当 Vue 正在更新使用 v-for 渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染

这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态的列表渲染输出。

key 的特殊属性主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes。如果不使用 key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试修复/再利用相同类型元素的算法。使用 key,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。

有相同父元素的子元素必须有独特的 key。重复的 key 会造成渲染错误。

sql分页查询

假设是从用户表里查询前10条信息

select * from user limit 0,10

nodejs的应用

  • restful api
  • 中间件
  • 命令行工具
  • api代理
  • 反向代理
  • 前端构建工具
  • 平台打包工具
  • 操作系统

nodejs的优缺点

优点:

  • 异步
  • 非阻塞

缺点:

  • 不适合CPU密集型应用

但是有了serveless,我们就可以把存在安全风险的,消耗大量CPU计算的任务都迁移到函数计算上

nodejs异步非阻塞的理解

异步是相对于同步而言的,是指不等请求完成就执行下一个动作的行为。同步是指要等待一个操作完成才能执行下一个操作的行为。

非阻塞是线程/进程相关的,它是相对IO而言的,如果执行一个函数后,当前线程仍处于运行状态,就意味当前线程是可以的继续处理其他任务,但要时不时的去看是否返回结果,这就是非阻塞。

一个线程/进程经历的5个状态,创建,就绪,运行,阻塞,终止。其中有个阻塞状态,就是说当线程中调用某个函数,需要IO请求,或者暂时得不到竞争资源,操作系统会把该线程阻塞起来,避免浪费CPU资源,等得到了资源,再变成就绪状态,等待CPU调度运行。 非阻塞相反,在不能得到结果前,函数不会阻塞线程,而会立即返回

难道面试官看我长得可爱,问题变简单了?

是否参加过校招,当时为什么不校招

没,渣本没有信心

二面(接近2h,挂)

大概在两天后,收到了二面通知短信,约在晚上面(心疼扣钱,真是个贫穷的小女孩了)

有两个面试官交替面试,其中有一个说是团队的老大

流程图的功能设计

可以从封装,继承,多态的角度考虑,主要考察的是需求理解能力和代码设计能力,开放性问题,答案有很多,我就不再赘述了

闭包

这个是前端必会的问题。如果有不懂的可以看<<你不知道的JavaScript(上卷)>>,讲解的很详细。

如果一个函数可以访问其他函数作用域的变量,那这个函数就形成了闭包。

function f(){
    var a=1
    function closure(){
        return a
    }
    return closure
}

闭包优点

  1. 可以让一个变量保存在内存中,不被垃圾回收机制清除
  2. 可以避免变量的全局污染
  3. 可以定义模块,将操作函数暴露到外部,细节隐藏在模块内部

闭包缺点

  1. 容易造成内存泄漏
  2. 闭包对性能会产生负面影响,包括处理速度和内存消耗

内存泄漏

如果一个变量长期存在内存里,没有被垃圾回收机制清除,就会产生内存泄漏。

执行上下文

执行上下文可以简单理解为一个对象,它包含三个部分:

  • 变量对象
  • 作用域链(词法作用域)
  • this指向

类型可分为:

  • 全局执行上下文
  • 函数执行上下文
  • eval执行上下文

代码执行过程: 1.创建 全局上下文

2.全局执行上下文逐行自上而下执行。遇到函数时,函数执行上下文被push到执行栈顶层

3.函数执行上下文被激活,成为 active EC, 开始执行函数中的代码,全局执行上下文被挂起

4.函数执行完后,callee 被pop移除出执行栈,控制权交还全局上下文,继续执行

call,bind,apply

这个答上来了,比较简单就不写了,不了解的可以自行搜索

水平垂直居中

水平居中:

  • 行内元素:text-align:center
  • 块级元素:margin:0 auto
  • display:flex+justify-content:center
  • position:absolute+left:50%+transform: translateX(-50%)

垂直居中:

  • line-height:height
  • display:flex+align-items:center
  • position:absolute+top:50%+transform: translateY(-50%)

水平垂直居中:

  • position: absolute+top: 50%+left: 50%+transform: translate(-50%,-50%)
  • display:flex+justify-content:center+align-items:center

方法不只这些,有兴趣的同学可以自己实现

vue的响应式原理

面试常见题,不会的可以搜下

virtual dom的diff原理

虚拟dom的产生是在浏览器的解析阶段开始的,而浏览器的解析又可以分成以下部分:

  1. html解析形成DOM树
  2. css解析形成css 对象模型(Css Object Model)
  3. DOM树和css Object Model合并成render树
  4. 页面布局(layout)
  5. 页面绘制(painting)

每次操作真实DOM,浏览器都会从头到尾解析一次浏览器,造成性能的巨大浪费。

为了解决这个问题,产生了虚拟DOM

虚拟DOM是对真实DOM的结构的抽象,它可以将vnode渲染成真实的DOM,通过和真实DOM的diff比较,对比新旧虚拟节点之间有哪些不同,然后根据对比结果找出需要更新的的节点进行更新。

Vue的diff算法是仅在同级的vnode间做diff,递归地进行同级vnode的diff,最终实现整个DOM树的更新。

父子组件传参

  • 父传子: prop
  • 子传父:$emit
  • eventbus
  • 跨多层组件:provide/inject

怎么改变一个数组

怎么改变一个对象

怎么改变一个基本类型值

这三个问题过于基础,不了解的可以看vue文档

性能优化

这个问题最好是结合自身项目经验回答

公司的技术架构

这个涉及公司的问题就保密了

数据库索引的实现原理

具体实现请参考附录2

OSI七层模型

面试的时候有点小紧张,没有说全

  • 应用层
  • 表示层
  • 会话层
  • 传输层
  • 网络层
  • 数据链路层
  • 物理层 每一层都可能发散往深层次问,面试官对我的回答不是很满意,没有继续追问

最小堆原理

这个问题没有答上来,面完以后看了不少关于堆的文章,感觉这篇写的比较好 看动画轻松理解「 堆 」

后记

面试是一个发现自身不足的过程,可能是年限原因,考察我的都是基础,我的数据库实现原理方面答得不是很好。面试官的需求是一个不限于前端的技术人员,需要你对数据结构与算法,数据库,编译原理,操作系统等底层都有深层次的了解,并在一个方向专精。

有准备面试的小伙伴可以关注我的项目algorithm-js,涉及到很多面试知识点,包括:

  • 红宝书js基础
  • 设计模式
  • 数据结构和算法
  • vue源码剖析
  • 你不知道的js读书笔记
  • 计算机网络

文中如有错误,欢迎在评论区指正,如果这篇文章帮助到了你,欢迎点赞和关注。

有复习基础知识准备面试的小伙伴可关注我的github博客,你的star✨、点赞和关注是我持续创作的动力!

附录

  1. 狼叔:如何正确的学习Node.js

  2. MySQL索引背后的数据结构及算法原理