两年的前端职业生涯,见识了商业的瞬息万变和残酷竞争。
今年的两个项目按照测算其实都能达到40%以上的毛利率,而且市场需求极其旺盛,也符合国家长期产业规划布局,开发周期短,资金周转率高,技术壁垒高,只要能持续盈利两年,慢慢摊销研发成本,日子就会好起来。立项的时候每个人都满怀期待,都相信肯定能大赚一笔。
然而短短几个月时间,政策和商业模式就能天翻地覆,换了人间。这一切现在都化成了泡影,行业内总会有聪明人想赚快钱,一家互联网公司把核心算法全部公开,一次性几千元买断使用权,任何人都可以拥有核心技术。
技术泛滥的后果就是大量黑作坊进场,黑作坊成本低廉,供应链完善但是品控一般,黑作坊进场不可避免就是血腥价格战,而大部分硬件厂商都是重资产模式,运营成本高昂,轻易就被华强北黑作坊击败。
这种情况下,自研核心技术,自建工厂反而变成了劣势。今年项目组全年净亏损**多万,**多万对集团来说不值一提,但到了具体的项目组,压到每个人的头上,真如泰山压顶一般,难以承受。我现在很迷惑,自主研发,遵纪守法,对员工好,品控优良,难道这些都有错吗?
也许这就是大势吧,势来不可挡,势去不可扼。虽然集团仁慈,全额发了年终奖,但随着项目组剧烈的调整变动和不断的更换领导,我心态也渐渐落入低谷。心累了,一切的心血都付之东流,突然就不想干了。看着自己住的员工价别墅,高档餐厅,还有诗一样的办公环境,真如一场梦境。现在梦醒了,就该搬回城中村里继续搬砖了。
最近在频繁面试,写写感悟吧,其实32岁这个年纪,没到35,简历基本还能通过初筛,面试官其实也,愿意和你聊聊天,聊聊项目,说说工作感悟啥的,气氛也比较轻松,以谈话为主。这一个多月时间面了欢聚,字节,cvte,联通,玛卡和云宏,华为OD七家,除了字节成了备胎,华为OD交了白卷,云宏不匹配之外。其他全部通过,超过50%的通过率,还是很开心的。
第一家是广州玛卡,是个创业公司,17年我用过他们产品,很有好感就投了,因为我要价3w,没有相应的开发岗位,所以就直接安排面架构师,一面是CTO,很干练,年轻有为,估计也是大厂出来的,问的东西都很有深度,单链表反转,长短轮询,前端vitals优化,keepalive原理之类的,然后手撸了一个快排算法,面试通过之后,第二天就到CEO面,效率很高,CEO的履历我面试前查过,是工商管理毕业的,不懂技术。所以面试的时候特意跟他聊了聊老东家关于项目周转率和规模成本的控制,CEO很感兴趣,在这方面和我聊了很多,我也很长见识。到最后是例行打压工资环节,他问我如何看待有些毕业生一毕业就有我这样的水平,而且体力更好,头脑更灵活,问我是怎么看待的。他着重强调了而且二字。我告诉他,我也负责招聘,我们集团每年招聘500多研发毕业生,一年后能有卓越成绩的只有3-4人,1%都不到,贵司现在就招一个架构师,你怎么能保证你招进来的毕业生就能胜任业务,就是这1%呢?CEO听完笑了笑,没说话,然后说如果你现在能定下来,就能拿到35w年薪。我不喜欢这种紧迫的感觉,所以直接回复他,考虑一周再答复您,也就是婉拒了。
我这里插一句,其实招聘就是玄学,除了学历之外,其他的都可以造假,而且没法证伪,一个人能不能胜任业务,能不能融入团队,性格有没有缺陷,通过两三场面试是很难看出来的。所以CEO讲的毕业生一毕业就有我这样的水平,而且体力更好,头脑更灵活,这种情况根本就是一个伪命题,他是不可能提前知晓这个人能否胜任。大公司招人都要靠绝对的数量来抵消这种不确定性,小公司只招一个人,那就只能听天由命了。
然后就是联通,面了两轮技术面,都不是很难,很重基础,我想应该是因为国企和民企的侧重点不一样吧。但面完之后,我意识到一个严重的问题,就是大厂都是在用react,而我几乎没有react的经验,又想要高薪,这样就只能去小公司了,但去小公司又没有保障,自己也不甘心,所以干脆选择闭关,过年那十天在B站找视频,开始速成react,redux,saga,然后看了umi,dva,antd和antv,直到我看完了antd pro和ProComponent,我感觉我react已经入门了,应该可以继续面试了,此时已经是大半个月之后,过完年的事情了。
第三家是cvte,效率也特别高,一周之内三轮面试,问的特别深入,都是要阐述原理的那种发散性问题,比如你觉得为什么cookie不能跨域、浏览器是怎么实现跨平台的、同时并发20个http请求,但每次只能有三个请求发出去,如何实现、1000个if,elseif嵌套在一起怎么优化、settimeout会不会阻塞ui、webpack的CDN怎么玩等等,都是这种很发散的问题,还好我以前也不是正经的前端,天天玩硬件和通信,基本都能答得上来,最后终面是视频笔试,给面试官共享屏幕写代码,一共二个题,只记得其中一个:判断一个字符串中的{}是否闭合。要求先写测试用例,然后编码,最后执行用例看结果,我用栈平衡算法写的,我感觉用正则应该也行,但是我不太会,就没敢写,最后栈平衡也通过那些测试用例了,终面通过。
然后是欢聚,也是广州的大厂,除了基础之外,还问了好多关于视频原理的问题,比如STUN和ICE区别,h264编码原理,mp4预加载过程等等,考察的很深入,很重基础,和cvte面的感觉差不多,很多东西都是面试官聊的时候临时问出来的,靠刷题是绝对过不了的。
之后是字节,字节在广州是飞书团队。不得不说字节是真的拼,hr和面试官,直接约我周日面,面了一下午,听说字节是996,然后到了周日也不休息,还要来面试吗,太夸张了吧?搞不太懂。不过面试官非常nice,出了一个场景和我讨论如何实现一个绘图需求, 主要是关于canvas的优化方案,我给出了分层渲染,编码压缩,图形碰撞检测的一些方案。图形这一块我主要是研究vr和3d这些,canvas用的很少,我感觉面的效果不是很理想,面完面试官也没给结果,估计就成了字节的备胎了,和当年在深圳面平安集团的感觉是一样一样的,隔个十天半个月就回来诈个尸,喊你继续面。那我也把你当备胎,互为备胎,哈哈。
然后是华为OD,开始还以为是华为在招人,就答应面试了,然后面的时候告诉我是华为外包,一听华为外包就火大,一下子让我想起当年在深圳被中软欺负的事情,本想着当场拒了的,然后那个hr居然用钱诱惑我,说我找工作为了什么,就是钱啊,外包也能给你很多很多的钱,不比正式员工少,只要你能面过,你没有理由拒绝的。好吧,你赢了,看在钱的份上就继续参加,然后hr给了我一个连接,进入之后是一个倒计时,90分钟三道算法题,具体题目:一个是大量数字排序(快排),一个是大量字符串匹配(KMP),还有一个是组织结构筛选(B树后序遍历)。然后每个题都有空间和时间复杂度的限制,一下我就傻了,我大概知道是用这三个算法,但是手撸还是有点费劲,时间复杂度都不达标,所以挣扎了50分钟就放弃了,交了白卷。没想到时隔许久,又栽在华为外包上了,虽然这次没有给我造成经济损失,但侮辱性极强,我以后再也不参加任何和华为有关的面试了,真的受不了了。
最后一家云宏,他家约面试比较晚了,我当时已经接了offer,也提了离职,新房子都租好了,所以就比较轻松,面试官也挺好的,看我也没有求职需求,就一直在跟我介绍自家的业务。这其实是一家小而美的行业独角兽,在通信虚拟机行业近乎垄断级别的存在,感觉他家老板眼光很独到,找到这样一个赛道,几乎没有竞争对手,躺着就把钱赚了。真是生了一双慧眼啊。
这次的跳槽面试就这样了,前端我是从17年自学转行,19年自学完成开始找工作,那一年我30岁,在深圳四处碰壁,拿着7k的工资,到31岁翻倍到18k,今年32岁又有了一次涨幅,两年间翻了接近四倍。前端程序员这个行业真的是锲而不舍,金石可镂,只要扎扎实实打磨技术,付出就会有回报,也祝大家都能心想事成
---------------这是分割线-----------------
下面是我最近遇上的一些题和我经常面别人的题,希望对大家有所帮助
-
BFC是什么
-
函数this指向
-
长轮询和短轮询区别
短轮询由浏览器控制定时器,长轮询由服务器控制定时器
-
307状态码意义
实现幂等性
-
时钟角度
-
常用的vitals项
TTFB,LCP,CP,CLS
-
元素如何居中
-
css中哪些属性能够继承
-
electron 调用系统函数
libuv中使用binding
-
实现一个简单RPC调用
-
STUN和ICE区别
ICE是通用标准,STUN是一种常用的NAT穿透技术
-
h264编码原理
I:关键帧,P:前项帧,参考前一帧生成画面,B:双向帧
-
数组去重
Set,lodash.uniq,原生方法
-
concat会不会改变数组
-
如何判断图形被选中
获取点击位置, 射线法
-
vue的keepalive原理
在VNode中设置一个标志,跳过从新渲染和数据获取
-
快排时间复杂度
最慢n2 一般nlogn
-
一个函数中有100个if,else如何优化
策略模式
-
前端图片压缩方法
canvas, new Image()
-
你项目中为什么不用canvas压缩图片,却要自己写转码函数
-
你的转码函数为什么用多种语言重构过,谈谈node,java和go的区别
node是单进程,异步IO,发布订阅模式,适合IO密集型应用,不适合计算密集型,是并行弱,并发强的一种语言
go可以发挥cpu多核优势,适合计算密集型应用
java适合大型应用后台,特点在于分布式,服务发现,动态扩容,负载均衡
-
cookie如何跨域
-
如何判断单链表有环
我: 给指针一个生命周期,生命长度为链表长度,生命结束时还没走出链表,证明有环.
再想想
我: 快慢双指针,如果快指针追上慢指针说明有环
这两种方案有何优劣
第一种适合链表状态已知的情况,有局限性
-
es6的import和commonJS引用有何区别
import相当于C++中的#define,是一个指针, 在打包时就执行了, require是一个实例,在运行时才执行
-
同时并发20个http请求如何做到
用函数体发送
-
同时并发20个http请求,但每次只能有三个请求发出去
设计了一个带索引值的消息队列
-
aria-label了解吗?
一种针对盲人的web设计规则
-
settimeout会不会阻塞ui,为什么
不会,ui由v8控制, timer,io,net这些由libuv控制,两者互不干扰,只有大量计算才会阻塞UI
-
如何处理大量计算
多线程+消息订阅
-
优化webpack打包速度
dll, tree-shaking, cdn
-
webpack的hash有哪几种
hash,chunkhash,contentHash
-
如何配置CDN
externals
-
MP4和flv有什么区别
区别不大,都是容器,mp4通过多个buffer缓冲来预加载,flv直接获得流
-
凸图形和凹图形如何判断碰撞
-
canvas优化方案
多图层渲染(参考H264)
-
编程题
判断一个字符串中的{}是否闭合 (先写测试用例 {{]), 123, }{}111, {\t\n\r}, {\}} {a:123} , 大概就是这么几种情况吧,然后我写了一个堆栈平衡的算法,勉强通过)
function(str:String):Boolean=>{ if(typeof str !=='string' || !str) return false if(str.indexOf('{')===-1) return false const stack :String[] =[] let startNumber=0 str.split('').forEach((i,index) => { if(i==='{'){ stack.push(i) startNumber=index } if(i==='}'&&startNumber>0){ if(stack.length>0){ stack.pop() }else{ return false } } }); return stack.length===0 }
手写快排算法和插入排序算法
//快排
function qsAdjust(arr: number[], low: number, high: number): number {
const temp = arr[low];
while (low < high) {
while (low < high && arr[high] >= temp) {
high--;
}
if (low < high) {
arr[low] = arr[high];
}
while (low < high && arr[low] <= temp) {
low++;
}
if (low < high) {
arr[high] = arr[low];
}
}
arr[low] = temp;
return low;
}
function qs(arr: number[], low?: number, high?: number): number[] {
if (high <= low) return;
if (!low) low = 0;
if (!high) high = arr.length - 1;
const standard = this.qsAdjust(arr, low, high);
this.qs(arr, low, standard - 1);
this.qs(arr, standard + 1, high);
return [...arr];
}
//插入排序
function insert<T>(array: Array<T>): Array<T> {
for (let i = 0; i < array.length - 1; i++) {
const value = array[i + 1];
let j = i;
for (; j >= 0 && value < array[j]; j--) {
array[j + 1] = array[j];
}
array[j + 1] = value;
}
return [...array];
}
-
一个json结构的组织层级[{id:1,children:[]}, {id:2}],从中删除一个节点
function clearTreeNode(tree,id){ if(!(tree instanceof Array) || isNaN(id) || !tree.length) return false let find=false for(let i=0; i<tree.length;i++){ if(tree[i].id=id){ tree.splice(i,1) find=true }else if(tree[i].children&&tree[i].children.length){ find=clearTreeNode(tree[i].children,id) } if(find) break; } return find }
-
单链表反转
while(n1) n0=null n1.next=n0 n0=n1 n1=n2 if(n2){ n2=n2.next } }
-
前端的未来是什么
5g时代嵌入式,vr和音视频造前端会普及
-
遇到过压力最大的事是什么
-
职业生涯中感觉最困难的是什么
-
遇到过最不能忍受的事情是什么
-
对你影响最大的人是哪位
-
一个技术团队中最重要最需要关注的是什么
-
为什么离职
-
是否主导开发? 前端团队规模? 项目用户多少?
前端基础
-
元素如何居中
-
css中flex:1 什么意思
-
flex能被继承吗?
-
sass中变量怎么定义
-
与css相比sass优势和不足
-
true || false ? 1 : 2 输出是什么
-
父子组件通信
-
生命周期,什么时候请求向后端数据,渲染了几次
-
router 有哪些形式, 区别是什么
-
设计数组增删改方法, 要求不能改变原数组
-
v-if和v-show区别【Vue】
-
为什么data要返回一个函数【Vue】
-
useEffect, 第二个参数什么意思, 不填会怎么样【React】
-
如何更新组件状态, this.state.name='A'可以吗? 为什么【React】
-
给实习生解释泛型/ type interface区别/ interface 有什么用
-
给实习生解释redux【React】
-
给实习生解释vuex【Vue】
-
场景:logo, 测试环境下显示logoTest, 生产环境下logoPro, 代码怎么写
-
import require 有何区别, 按需加载如何实现
计算机基础
-
如何判断单链表有环
-
二叉树前序遍历abc,后序遍历是什么
-
快排时间复杂度
-
一个函数中有100个if,else如何优化
-
内存垃圾怎么清理
-
cookie如何跨域
项目经验
-
websocket : 101状态码
-
websocket 和http区别
-
长轮询和短轮询区别
-
gzip原理
-
描述你设计的图片压缩算法
-
优化webpack打包速度
-
webpack输出到cdn,如何配置
-
webpack的hash有哪几种
-
常用的vitals项
TTFB,LCP,CP,CLS
-
304状态的意思,哪些类型文件需要设置
尴尬专用
-
期望年薪多少
-
上一份工作中最有成就感的事情
-
压力最大的事请是做什么,怎么克服的
-
一个技术团队中最重要最需要关注的是什么
-
为什么离职
网友评论