84
头图

跳槽周期跨度

什么时候动了想法

大概在去年11月份的时候,我负责的业务线一直做不出成绩。而且整个公司的前端技术设施,都是我一手搭建出来的,再待在公司,没什么可成长的空间,就想跳槽了,期间考虑了几个可能性:

  1. 出国工作:这个想法来源,主要是看了某位网友肉身出国到新加坡的虾皮到新加坡打工两个月的经历分享,觉得挺有意思,也想尝试下,后面投了一些跨国企业,没啥反馈,估计是卡学历,所以就放弃了,后面再想想弥补外语的可能性
  2. 进入大厂:很多大厂都卡学历,即使是内推,也会被卡面试流程,我被小红书、京东、腾讯、美团,拼多多、虾皮、携程、喜马拉雅卡学历和卡面试进程,所以,能选择的大厂很少,最终入职了 B站

面了哪些公司

  1. 热身阶段(11月下旬 - 12月中旬)

    • 彩云科技,offer
    • 天壤智能,offer
    • 掌门一对一,offer
    • 帷幄匠心,offer
    • 驰骛科技,offer
    • 坚果云,二面挂
    • 乐言科技,二面挂
  2. 正式阶段(12月下旬 - 2月下旬)

    • 微盟(海外电商),一面挂
    • 字节(广告商业化),一面挂
    • 字节(线索中台),二面挂
    • 字节(抖音生活服务),二面挂
    • 网易(严选),四面完,最终评审挂
    • 七牛云(低代码平台),三面完,后续无反馈
    • B站,offer
    • 中通快递,offer

复习备战花了多久,面试到入职,花了多久

11月 - 2月 一直在陆陆续续准备,持续了 3 个月,主要是准备复习、复盘、刷算法
从开始面试,到入职,差不多 3 个月时间

做了哪些准备

主要准备了以下几个方面:

  1. 简历,仔细梳理了最近的工作经历,项目上做的事情,用到哪些技术
  2. 笔试,主要是算法和编程题
  3. 技术知识点查漏补缺

复习了哪些内容,刷了哪些题

  1. 八股文
  2. 编程题,手写各种方法
  3. 算法题
  4. React/Mobx/Vite && Webpack
  5. 自己写的博客

八股文

这块没啥好说的,把各大社区各位大神经常分享的一些文章看了下,再就是针对计算机基础知识和网络基础知识,做了一些总结,大概看了下面这些文章:

  1. 浏览器工作原理与实践
  2. 图解V8
  3. 从多线程到Event Loop
  4. 前端年后面试真题,会80%直接进大厂副本

编程

刷了下基本会手写的面试题以及再把面试过程中遇到的手写题总结下,基本上都还好

算法

算法这块不是我的长项,基本没接触,主要是把 LeetCode 热题 HOT 100,Easy 难度简单刷了下,针对大厂频出的算法题,看不懂的,就背答案,比如经典的反转二叉树、任意两个数的和等于 Target、反转单向链表等

后面根据一些面经和文档,比如:前端年后面试真题,会80%直接进大厂副本,做了一些针对性地练习和巩固

框架

React 部分复习了 setState原理、 diff 原理,深入了 hooks 和 fiber 原理,当然这里的深入不是去读源码,因为时间来不及,而是参考了比较多的文章:

  1. React技术揭秘
  2. React 进阶实践指南
  3. Vite
  4. 前端年后面试真题,会80%直接进大厂副本

Mobx 由于我日常使用比较多的,也被面试官深入问过,就自己搭建过前端脚手架和看了下 React 进阶实践指南里面有一篇讲了 Mobx。主要了解框架的主体逻辑、响应式原理、依赖收集的实现
此外也总结了一下 Redux 和 Mobx 的特点,因为面试官大概率会问:Redux 和 Mobx 的区别?

博客

由于本人经常会写播客,这点在投递简历的时候,是非常大的一个加分项,在多个技术社区有同名账号,经常发表一些文章,会受到面试官的青睐,我最近的面试,都有被面试官提到,你的博客写的不错,而且面试官也会从你的博客中来提问你,我就被问到以下问题:

  • Webpack 如何实现热更新的?
  • React 和 Vue 的选型?
  • Redux 和 Mobx 的区别?

这些问题,我都在博客上记录了,所以都是信手拈来

重点补了哪些能力和短板

  1. 技术部分:算法、编程题、对框架的细节思考(不仅仅是停留在使用层面)
  2. 业务部分:将自己对业务的理解和思考进行了总结
  3. 管理部分:归纳和提炼

面试中暴露了哪些问题,怎么应对的

思考和表达的连续性

前期热身的时候,准备内容的结构化不足,遇到有些没有准备到的问题,临场思考和组织,或者一遍表述一遍思考,导致表达的结构性和连续性较差,表现上就是重点不够、啰嗦、回答不上

解决:针对几大类问题梳理了整体的思维导图,表达的时候,跟进面试官的侧重点,挑选关键点进行结构
化表达

过往经历的思考不足

当面试官聊到过往短板问题或者低谷经历时,一开始的回答有点浮于表面,并且有一些规避的回答,受到了面试官的质疑

解决:认真、客观地重新梳理了对应的问题,从主观、客观层面进行重新组织语言进行回答

印象深刻的事情

每个公司面下来的感受

  • 字节:我自己的意向是字节跳动,连续面了三个部门,后面字节挂了两个部门,又被其他部门捞起来,,面到后面,越来越没底气,一方面自己的技术深度不够,另一方面,感觉面试官都很年轻,不会往你的优势方面去进行引导(面试经验不足),有的部门,面的感觉还可以,都挂了,很烦
  • 网易严选:网易严选的流程最长,我面了一个多月,当字节跳动挂了之后,网易严选是我最意向的部门,技术栈和业务方向匹配,该部门接下来一年要做的一些事情,也跟我的职业发展比较匹配,但是,四面完之后,就给我挂了,很遗憾,估计是被其他候选人给 PK 下去了
  • 七牛云:一面问八股文,手写代码,比如实现一个 call/apply 方法等,二面很常规,问问简历上的事,三面由部门负责人来面试(产品经理),感觉还可以,还让我加了微信,但后面流程一直没有推动,我问了 HR 多次,HR 给我的反馈是对我的印象挺好,希望保持联系,但后面流程就推动不下去了,再联系 HR ,就没回复
  • B站:全程聊的都还可以,比较顺利
  • 坚果云:印象最深的就是二面了,要开始二面前, HR 先联系我,说是一个开放性的题目,让我二选一,我选择了其中一个,让我做整体的思考,我做了大量的后端知识、服务端知识,但面试官只问前端方面的知识,沟通的不是很顺利,整体面下来,感觉双方的理解都是有问题

哪些经历让自己很难熬

字节和七牛云的 offer 一个都没拿到

字节面的感觉还可以,第二天就挂了,很难受,心态有点蹦
七牛云三面完之后,我等了一周左右,没给我反馈,我一直在推进,包括联系三面的面试官,询问结果,就是不给反馈,挂了也没任何反馈

最终抉择

当时手头上只有掌门一对一的 offer ,掌门一对一,HR 在催我入职, B站和网易严选还没有面完,无法拒绝,很纠结,当时做的选择就是,先入职掌门一对一,哪会儿中通联系上我,我就再面了一个中通,拿到了中通的 offer,然后再等B站和严选的流程了,自己对严选是非常意向的,但严选终面完还是被挂,就很头疼,在面严选的过程,B站正式 offer 发了,只能选择B站

如何克服了过程中的困难

  1. 定好策略,稳住心态
    跳槽的过程中不是来一家公司就面一家公司的,而是要根据自己的情况循序渐进。像我这样后面 offer 还比较少的时候,虽然心里也慌,但还是准备了一些兜底的策略,这点非常重要,而且本人是裸辞的情况下,面了很长的时间,心态一定要稳住,特别是互联网寒冬时期
  2. 与人交流,开拓思路
    我会和学长、靠谱同事、靠谱猎头进行交流,一方面可以从他们的角度看出自己的不足,另一方面也可以从他们那里得到帮助和思路

其他的心得体会和经验

面试的 4 个环节:简历准备 - 投递策略 - 面试和复盘 - offer 谈判和选择

  1. 简历准备
    简历准备不是要跳槽的时候才准备的,而是日常工作中要经常做总结,跳槽前对这些总结进行梳理归纳提炼为简历
  2. 投递策略
    职业生涯中每个阶段的跳槽,可能会有不同的策略,常规好用的策略是先找几家公司热身,然后再开始投递自己的目标公司,在投递过程中,时间节点也需要有一定的关注
  3. 面试和复盘

    • 面试可以通过一些公司热身试错,同时,在面试中要快速捕捉到面试官想挖掘的点,用简炼地话表达出来回应给面试官。如果面试官没有挖到你长项的部分,还需要考虑引导面试官,让自己展现出自己的长项
    • 在表达方面,如果直接表达不够结构化和清晰,可以先使用笔记或者思维导图梳理,然后自己预演熟练
    • 复盘很重要,要尽可能让自己犯过的错不再犯第二次,并且,复盘的内容是可以长期积累的
  4. offer 谈判和选择

    • 首先,要大概了解自己的市场价(对于大厂要了解自己的定级,对于中小厂要按市场水平),虽然这个比较难,但还是可能的
    • 如果有了解自己的市场价,那么在期望薪资这块,就可以报得有底气一些,也比较容易得到较高的涨幅。
    • 多拿 offer,通过技巧去让厂家自己在 offer 之间互相竞争,是相对容易的。虽然每个公司有自己的薪资体系,但招聘本质上是一个市场行为,厂家也要遵循客观规律

总结

跳槽是一项心力、体力、脑力都必须在线的活动

资料参考和分享

最后

欢迎大家加入B站,我在B站等你,随时可跟我交流面试经验

也欢迎大家关注我的博客

高频面试题整理

CSS

  1. css 重绘和重排如何理解
  2. 下面宽高各是多少
    <style>
        .box {
            width: 100px;
            height: 100px;
            padding: 10px;
            margin: 10px;
            background-color: #f00;
            box-sizing: content-box;
        }
    </style>
    <body>
        <div class="box">12312312</div>
    </body>
  1. span 标签在浏览器中偏移量是多少
    <style>
        .test {
            margin: 20px;
        }
    </style>
    <body>
        <div>
            <span class="test"></span>
        </div>
    </body>
  1. 为什么 marign 0 auto 无法垂直居中
  2. 控制 z-index 的规则有哪些
  3. 元素替换概念有了解吗?
  4. 移动端 1px 像素如何解决?
  5. 一个元素隐藏有几种方式?
  6. 讲讲 BFC
  7. css 选择器
  8. display 有哪些属性
  9. 三列布局如何实现
  10. css 栅格布局
  11. flex: 0 1 auto 的含义
  12. css 如何实现一个正方形盒子(随父元素)自适应

JS

  1. js 有哪些基本数据类型
  2. 讲讲闭包是什么?
  3. var、let、const 的区别
  4. es5 如何实现继承

    • 原型继承方式(这里要注意下,很有可能让你手写)
    • 寄生组合继承
    • 引申到 es6 的 Class 语法糖
  5. es6 有哪些新的特性
  6. map 和 waekMap 的区别
  7. js 中 this 指向
  8. 讲讲 setTimeout 和 setInterval 的差异
  9. 用过函数节流和防抖吗?
  10. localStorage, sessionStorage, Cookie 之间的区别
  11. 下面输出结果是什么?
    var count = 100;
    var obj = {
        count: 200,
        getCount: function() {
            console.log(this.count);
        }
    }

    const c = obj.getCount;
    obj.getCount();
    c();
  1. 下面输出结果是什么?
    var obj1 = { a: 100 };
    var obj2 = Object.assign({}, obj1);
    var obj3 = obj2;
    obj3.a = 200;
    console.log(obj1);
    console.log(obj2);
  1. 下面打印结果是多少
    var p1 = new Promise((resolve) => {
        resolve(1);
    });
    var p2 = new Promise((resolve) => {
        setTimeout(() => {
            resolve(2);
        }, 0);
    });
    var p3 = new Promise((resolve) => {
        resolve(3);
    });
    Promise.all([p1, p2, p3]).then((res) => {
        console.log(res);
    });
  1. 下面打印结果是多少
    async function promise2() {
        function p1() {
            return new Promise((resolve) => {
                resolve(1);
            });
        }

        function p2() {
            return new Promise((resolve, reject) => {
                reject(2);
            });
        }

        function p3() {
            return new Promise((resolve, reject) => {
                resolve(3);
            });
        }

        try {
            var p11 = await p1();
            var p22 = await p2();
            var p33 = await p3();
            console.log(p11);
            console.log(p22);
            console.log(p33);
        } catch(e) {};
    }
  1. 请描述下 new 的执行原理
  2. 为什么 Object.prototype.toString.call 可以判断出变量,而不是通过 Object.toString.call ?
  3. 讲讲 gc 原理
  4. js 如何解决数值精度问题
  5. 讲讲事件循环

浏览器

  1. 浏览器缓存原理
  2. 单页应用如何提高加载速度?

React

  1. 讲讲 fiber 架构
  2. 讲讲对 diff 的理解
  3. 讲讲对 hooks 的理解
  4. 讲讲 class 生命周期
  5. setState 原理
  6. hooks 为何有一些规则使用条件
  7. 聊聊 react 事件机制原理
  8. 讲讲 useCallBack 和 useMemo 的区别
  9. 讲讲 useRef 和 ref 的区别
  10. react 组件传递状态有哪几种方式

状态管理

  1. mobx 原理
  2. redux 原理
  3. mobx 和 redux 的区别
  4. 函数式组件特点,和 hoc 区别
  5. 讲讲 redux 中间件

微信小程序

  1. taro 源码如何实现的?
  2. taro 2.x 和 taro 3 最大区别是什么?
  3. 微信小程序原理是什么?

打包工具

  1. 聊聊 vite 和 webpack 的区别
  2. 模块化有了解吗,讲讲 import 和 require 的区别?
  3. webpack 的原理
  4. 谈谈摇树的概念
  5. webpack 热更新机制原理
  6. vite 原理是什么?

设计模式

  1. 订阅发布和观察者模式和什么之间的区别,实现一个订阅发布者模式

编程题

  1. 如何实现一个深 copy
  2. 实现一个 new
  3. 柯里话函数的实现
  4. 实现一个函数 calc
function calc() {

}
  • 对于任意参数,实现累乘功能
  • 对于两次同样的参数,结果缓存,比如 (1, 2, 3)、(3, 1, 2)
  • 对缓存优化
  1. 实现一个 apply
  2. 针对深 Copy,变种的题目
  3. 实现一个 ajax
function ajax(options) { }
  • 在实现的 ajax 基础上实现调用所有请求,等到所有请求结果成功之后,再返回结果
  • 在实现的 ajax 基础上实现请求顺序调用,第一个调用成功之后,再调用第二个,以此类推
  1. 实现一个 repeat 函数,根据传入的参数,间隔时间,打印次数,来输出 log

repeat(func, inteval, times){ … }

const r = repeat(repeatPrint, 10, 10);
  1. 用最精炼的代码实现数组非零非负最小值的索引 index
// 例如:[10,21,0,-7,35,7,9,23,18] 输出索引 5, 数值 7 最小
function getIndex(arr) {
    let index = null;
    ...
    return index;
}
  1. 该代码输出结果是什么?
const list = [1, 2, 5]
const square = num => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(num * num)
        }, 1000)
    })
}

function test() {
    list.forEach(async x => {
        const res = await square(x)
        console.log(res)
    })
}
test()
  1. 手写一唯数组转换树节点
var array = [
    {pid: 4, id: 6617, name: "a",subNode:[]},
    {pid: 5, id: 666, name: "a",subNode:[]},
    {pid: 4, id: 6616, name: "a",subNode:[]},
    {pid: 6616, id: 66161, name: "a",subNode:[]},
    {pid: -1, id: 0, name: "a",subNode:[]},
    {pid: 0, id: 4, name: "a",subNode:[]},
    {pid: 0, id: 5, name: "a",subNode:[]},
    {pid: 4, id: 10, name: "a",subNode:[]},
    {pid: 10, id: 451, name: "a",subNode:[]},
    {pid: 0, id: 98, name: "a",subNode:[]},
    {pid: 98, id: 23, name: "a",subNode:[]},
    {pid: 98, id: 523, name: "a",subNode:[]}
];

var toTree = function(tarArray) { }

toTree(array);

算法题

  1. 实现一个反转二叉树
  2. 一个迷宫,最短路径生成
  3. 实现单向链表反转
  4. 实际场景算法题
  5. twoSum 得到两个数的之后等于 target

其他

  1. 聊聊业务上的事
  2. 聊聊最复杂的业务如何处理的
  3. 如何做性能优化
  4. 聊聊前端脚手架
  5. 带团队中有哪些难点
  6. 聊聊迭代流程
  7. Git 如何覆盖某次 commit
  8. 长列表滚动,你怎么优化的
  9. 印象中最深的一件事

本文参与了 SegmentFault 思否征文「如何“反杀”面试官?」,欢迎正在阅读的你也加入。


野生程序猿江辰
902 声望2.4k 粉丝

前网易高级前端开发工程师 | 矩阵创始人 | 独立开发者