前言
内容包括面试考点,答题技巧,以及一点工作后的经历... 读者可以根据右侧导航目录,按需阅读,希望各位都有所获。
您的简历,与岗位要求不符
开篇不想暴击,但很有必要。往往我们为了面试,准备了很久,投了心仪的厂子,结果等来的不是面试通知,而是一封冰冷的邮件... 您的简历,与岗位要求不符
一般这种情况可以总结为几类,评论欢迎补充:
-
- 您是真滴菜,掰掰。
-
- 年龄太大,水平一般,我们要的是新鲜血液,掰掰。
-
- 学历太低,掰掰(厂子的要求越来越高了)。
-
- 内容太多,没有重点和主次,看不到实质内容,掰掰。
重要分析一下第 4 点,可以解读出很多东西:
-
- 内容太多,可能你写了满满一页,全是没营养的东西。建议:将亮点罗列出来。
-
- 可能你前后端都擅长,所以写了很多后端的内容,没有分清主次,我们招的是前端。
-
- 内容太多,但看不到真实的东西,比如你写的代码,我觉得你在吹牛。需知:
「Talk is cheap. Show me the code」,建议:简历里带上你的 github、掘金等链接,若没有?还不赶紧动起来!
- 内容太多,但看不到真实的东西,比如你写的代码,我觉得你在吹牛。需知:
-
- ...待补充
引导面试官
简历上面写了什么,决定了面试官会问你什么。如果你写的很泛,除非你真的很全面无敌,否则情况会很糟。
面试是有技巧的,简单的一问一答太过死板,试着在回答的时候引申向你擅长的领域,抛出一个个关键词诱导考官提问。
具体的例子,下文会涉及。但在此之前,我们需要做足功课,务实基础。此外,请务必准备一些杀手锏,在需要的时候亮瞎考官的……,比如 HTTPS 所有加密算法,chromium 进程 IPC 原理,斐波拉契第 n 数的 logn 解法,浏览器渲染过程,Vue 编译器架构,快排以及手写 V8 排序。
数据结构和算法系统练习
算法是大厂必考的项目,这里笔者提供 leetcode 字节跳动的企业题库,后面会慢慢补齐其他厂的。
高频基础
进入正题,前端要往深了走,基础很重要。
闭包
定义:有权访问另一个函数作用域中的变量的函数。
产生原因:先解释下作用域链,然后说明当前环境存在指向父级作用域的引用。
应用:定时器 / 事件监听 / ajax / Web Worker 等都有涉及,关键就是使用了回调函数……
面试时可以展开的点,可以引出下一个话题:闭包变量存在堆中一个名为 [[scope]] 的对象内,同时闭包也常以 高阶函数 的形式创建,V8 的 垃圾回收 机制也涉及到了闭包。
堆栈及 V8 垃圾回收
讲到闭包,就会涉及到内存存储空间的知识,进而可以引申到垃圾回收机制 GC。
我们知道:栈中保存变量,函数调用完,栈顶空间自动销毁,然后切换执行上下文,假如存储对象很大,切换的开销自然也变得巨大。于是,堆就出场了。
强调:V8 的 GC 作用的是堆而不是栈。
- V8 设置堆内存上限为 1.4G,原因:js 是单线程执行,堆内存在进行
非增量垃圾回收时需耗时 1 秒之久,这期间会导致 js 暂停、应用卡顿,造成性能下降,显然,1.4G 是经过深思熟虑的。 - 新生代临时内存上限 32M:涉及 Scavenge 算法,分正在使用的 from 空间,闲置的 to 空间。
- Scavenge 缺点:浪费一半空间,用在大空间复制效率极低,所以老生代换了算法。
- 老生代常驻内存:涉及
变量晋升,两个算法mark-sweep 标记清除,mark-compact 标记整理。还有增量标记算法,这个算法优化将 GC 期间造成的 js 阻塞减少到原本的 1/6。 - 垃圾回收是在 Event Loop 的
微任务阶段进行。
GC 还可以展开的点:增量清理、增量整理、多核并行清理,内存泄漏,WeakMap、WeakSet 弱引用。
原型
回答时,可以按照以下顺序来回答。
-
- 原型对象概念:函数都会自带 prototype 属性 (箭头函数除外),该属性指向原型对象。
-
- 构造函数概念:new + 函数执行 = 构造函数,并返回实例对象。
let obj = new Fn()
- 构造函数概念:new + 函数执行 = 构造函数,并返回实例对象。
-
- 实例对象有个
__proto__属性,全名 [double underscore proto] 读作dunder proto即可。该属性指向构造函数的原型对象。
- 实例对象有个
-
- 原型链概念:
__proto__指向父类对象,接着不断追溯父类原型对象,直到指向 Object 对象为止,再上面只剩 null 了。明白了原型链,那么手写 instanceof 就不在话下了。
- 原型链概念:
-
- 原型继承,继承的优点和缺点,比继承更佳的方案:组合模式
列出几个常用的方法:
-
Object.getPrototypeOf(obj) // 获取原型对象,比如 instanceof 源代码 -
Object.setPrototypeOf(subClass, superClass) // 继承父类的静态方法 -
Object.prototype.hasOwnProperty(attr) // 检查对象自身是否有该属性 -
in // 检查对象或原型对象中是否有该属性 if (k in O) {} -
Object.create(proto, [propertiesObject]) // 一个不带任何原型链属性、纯净且高度可定制的对象,比如数据字典可以用 create(null) 代替 {} 初始化
Event Loop
这块算是面试的重头戏了,资料太多,照搬没有意思,认清注意下面几个点。
- 宏任务包括普通队列和延迟队列,宏任务内还维护一个微任务队列。
- 微任务前有个 nodejs 的
process.nextTick。 - 微任务末尾有一个
requestAnimationFrame,接着是 UI 渲染,Web Worker,注意这几个的顺序。 - 了解微任务的位置为什么在宏任务的末尾。
- Nodejs 的 Event Loop:注意 pending callbacks 挂起的系统操作回调,比如 tcp 错误的连接请求。
- Nodejs 的 setTimeout 小于 4ms 一律以 4ms 处理。
process.nextTick:是独立于 Event Loop 的任务队列,且在微任务之前执行。- 区别:Nodejs 微任务在每个阶段之间,且微任务队列具有最高优先级,注意特殊的 nextTick。
花点时间详细了解 Event Loop 里面的细节是很有必要的,毕竟主流前端框架中的批量更新,fiber 的调度,事务等都或多或少与之相关,在提高性能这一块 Event Loop 可以做的事情很多。
Promise
- 返回 promise 能解决回调地狱,错误冒泡将错误一次 catch。
- function* 为生成器函数,实现机制为协程,可以做到代码可控,不需要切换上下文。
- async / await 利用协程和 Promise 实现了同步方式编写异步代码的效果。
- 异步可控遍历:for...of + await 更优于 forEach + await 的地方是使用了迭代器
array[Symbol.iterator]().next()的语法糖,forEach + await 别用就对了。 - 高频面试题:手写 Promise 的各种方法。
常见的设计模式
设计模式并不是多么晦涩难懂的概念,我们日常开发中多少都会接触到。它是前人在实际生产项目中不断迭代、试错、修正、抽象而来的经验总结,使用设计模式可以让你的代码变得更加可维护、易于扩展。说人话就是平常能用就用,重构时必用。
-
工厂模式:组件化中常用的重构利器。
-
单例模式:分懒汉式和饿汉式,比如数据库连接,vuex、redux 等状态管理工具,甚至更复杂的场景,必须掌握。
-
观察者模式:太多地方用了,比如 Vue 响应式中的收集依赖和触发更新。
-
发布-订阅模式 与 观察者模式 的区别:在观察者模式中,观察者是知道 目标 Subject 的,Subject 一直保持对观察者进行记录。然而,在发布订阅模式中,发布者和订阅者不知道对方的存在。它们只有通过一个中间层,消息代理进行通信,同时是异步的。在发布订阅模式中,组件是松散耦合的,正好和观察者模式相反。
-
观察者模式 举例:你对某知名企业很感兴趣(你作为观察者知道企业大名),投递简历后企业维护你和其他面试者的简历(企业知道了你),当职位空缺时主动通知你和其他面试者。这个例子,双方是直接的关系。
-
其实还有:状态模式、策略模式 都比较常见,也比较简单,一看就会,实际开发中如果写烦了
if-else,也可以换换写法,优雅一下。 -
享元模式、中介者模式,emmm...跟 发布-订阅模式 极其的类似。
-
而 适配器模式(用于封装)、装饰者模式(用于增强功能)、代理模式(Vue3 的 Proxy)较易混淆,有兴趣就多了解。
主流框架
主要讲讲主流框架
Vue和React,包括但不限于:框架演进、框架横向对比、虚拟 Dom、渲染、响应原理、版本差异、Diff 算法等...
V8 执行 Js 的过程(即时编译 JIT)
- 1.
解释器通过词法分析和语法分析将源码转成 AST,根据 AST 生成执行上下文。 - 2.
解释器根据 AST 生成 V8 字节码。为什么不是二进制机器码:机器码太大,执行占用太多内存。 - 3.
解释器逐行执行字节码,遇到热点代码启动编译器进行编译,生成对应的机器码, 以优化执行效率。
针对 Js 运行的性能优化:
- 1.提升单次脚本的执行速度,避免 Js 的长任务霸占主线程,这样可以使得页面快速响应交互;
- 2.避免大的内联脚本,因为在解析 HTML 的过程中,解析和编译也会占用主线程;
- 3.减少 Js 文件的容量,因为更小的文件会提升下载速度,并且占用更低的内存。
科普:很多人在刚入门的时候对 V8、Webkit、JSCore、runtime 这几个词没有概念,或者傻傻分不清,笔者在这里简单梳理下。
- Js 是动态解释型语言:在运行时通过解释器进行动态解释和执行。
- 编译器:能生成二进制文件。
- 即时编译 JIT:一种热门的字节码配合解释器和编译器的技术。
- 比如 go 是静态编译的语言,可在不同平台交叉编译;java 也是,附带动态特性,有一层 jvm,可以跨平台直接运行。
- 静态编译:不依赖动态链接库,可以任意部署到各种运行环境,就是体积大一点。
- V8(Chrome 基于 JSCore 的升级版,性能更佳) / JSCore(起源于 Safari,是 WebKit 的默认 JS 引擎,手机端都是使用的 JSCore) 执行在 WebView 的 WebKit 渲染引擎中。
- JavaScript Runtime 用来执行JavaScript代码用的,为其提供了一个运行时环境,提供解释/编译、自动内存管理(GC)、对象模型、核心库等功能。
- V8 将 runtime 看成高级语言虚拟机,GC 等都在里面
- WebKit 和 V8 引擎都在渲染进程中。
AST
AST,似乎到处都有它的影子,包括浏览器、主流框架、Webpack 等打包工具、Babel、跨平台应用框架,如 uni-app 、Vue 转小程序。了解了 AST,之后不论是优化还是转换,不过是增删改查罢了。
Vue 的 template 编译,渲染机制
-
解析模版,生成 AST 语法树:
词法分析:使用大量的正则表达式对模板进行解析,遇到标签、文本的时候都会执行对应的钩子进行相关处理。
优化:其中涉及
静态节点优化,设置 static 属性用于 Diff 时剪枝,静态节点就是一些不带变量的文本节点,或者一些不带 if 和 for 的节点。用于在下次渲染时直接跳过。深度遍历 AST,标记静态节点以优化跳过比对,最后转为可执行的代码。
总结:语法分析 -> 语法分析 -> 优化
-
到这里,其实 AST 的任务已经结束。以下是 template 接下来的代码逻辑。
AST 会经过 generate 函数得到 render 函数,不同的节点有不同的 render 处理方式。render 生成虚拟 Dom,最后 patching,Diff,渲染 Dom。
3.引申:flutter、React Native 的渲染机制
Vue 的响应原理,忽略细节版
vue2.0 响应式原理 看这篇够够的了。
-
view 变化触发 data 更新通过事件监听
-
以下是 data 触发 view 更新
-
v2 中是递归遍历 data 中的所有的 property,并使用
Object.defineProperty把这些 property 全部转为 getter/setter,在getter 中做数据依赖收集处理,在 setter 中 监听数据的变化,并通知订阅当前数据的地方 -
具体:
-
1.实现一个监听器 Observer:对数据对象进行遍历,包括子属性对象的属性,利用
Object.defineProperty()对属性都加上 setter 和 getter。这样的话,给这个对象的某个值赋值,就会触发 setter,那么就能监听到了数据变化。 -
2.实现一个解析器 Compile:解析 Vue 模板指令,将模板中的变量都替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,调用更新函数进行数据更新。
-
3.实现一个订阅者 Watcher:Watcher 订阅者是 Observer 和 Compile 之间通信的桥梁 ,主要的任务是订阅 Observer 中的属性值变化的消息,当收到属性值变化的消息时,触发解析器 Compile 中对应的更新函数。
-
4.实现一个订阅器 Dep:订阅器采用 发布-订阅 设计模式,用来收集订阅者 Watcher,对监听器 Observer 和 订阅者 Watcher 进行统一管理。
-
限制:
-
无法检测对象属性的添加与删除,需要配合 set/delete
-
defineProperty 监听 array 是有缺陷的:改变 length 长度或者超出设置,监听都会失效。
-
性能问题,层级太深导致性能下降
-
所以 vue 在数组的原型方法上做了一些手脚 defineProperty(obj, 'push') 监听 push 方法
-
检测数组变化源码解析:
-
1.
Object.create(arrayPrototype)初始化一个以数组原型对象 Array.prototype 为参数的对象:Object.create(Array.prototype) -
2.将该对象里的所有数组方法用 definePrototype 重写
-
3.在数据 observer 绑定的时候,判断数据对象是否有
__proto__,有就将数据直接绑定上重写后的原型 -
4.如果浏览器不支持
__proto__,依据原型链,就将重写的原型直接挂在数据上好了。 -
5.这样当调用数组 api 时,可以通知依赖更新,如果数组包含引用类型,继续递归遍历监控
-
$set 原理:
-
如果目标是数组,直接使用数组的 splice 方法触发相应式。
-
如果目标是对象,会先判读属性是否存在、对象是否是响应式。
-
最终如果要对属性进行响应式处理,则是通过调用 defineReactive 方法进行响应式处理,最后通知订阅 notify。
-
总结:对象和数组都是通过递归遍历
Vue2 Diff
vnode 对象是树的递归遍历
O(n^3) -> O(n)- O(n^3) 计算:单个节点与旧 vnode 的依次比较,为 n^2,计算差异后遍历找到位置进行删除或增加,为 n,最终为 n^3
- diff 的必要性,算法优化能够同时减少回流和重绘,具体触发流程:
触发setter -> 触发通知 notify -> 触发 watcher 加进异步更新队列,eventloop 会清空队列,watcher 尝试执行更新函数 -> 调用渲染函数,重新计算 vdom -> 进行 diff
代码逻辑:
-
没有旧节点,直接创建新的。
-
新旧 vnode 不同,直接销毁旧的,创建新的。
-
新旧 vnode 相同,继续比较子节点:
其中 vnode 为文本节点,与旧不同则直接更新
子节点依旧是新旧之间的比较,只有新节点直接创建,只有旧节点则删除旧的,新旧又不同,开始 diff 核心算法,重点讲解:
-
while 循环比较新旧子节点:头索引跟头比较,尾跟尾,比完缩减往中间收拢,比较遵从:
-
头与头比较,相同则复用不作处理,同时头++,尾、头尾、尾头的目的都是为了复用
-
用 key 比较
-
map 表遍历查找
-
剩余节点,批量新增或删除
-
总结:能不动就不动,不行就移动,最后处理新建或者删除。相比React的Diff算法,同样情况下可以减少移动节点次数,减少不必要的性能损耗,更加的优雅。
Vue3 Diff 优化:
-
vdom:创建 vdom 的时候多了个 dynamicChildren 动态节点,patch 的时候只比对动态。
vue2 静态节点也会 patch。
-
vdom:节点变更类型用 patchFlag 细分,用位掩码组合,作为判定更新的依据。
vue2 如果是普通节点,会通过内置的update钩子全量进行新旧对比,然后更新;如果是component,则会在prepatch阶段进行判断,有变化则会重新触发forceUpdate,造成很多无用的重复对比。
-
diff 核心变化:用数组 map 记录节点变更的位置以及新增的节点 + 最长子序列(如果递增则位置不变)。
-
相同事件缓存不会重新生成。
React16 Diff
vnode 对象是链表的循环遍历,与递归不同的是可以设置暂停和恢复,根据调度展开的优化代码。
-
复用没有变更的节点,用 key。
-
先比较两棵树的根节点,若是不同的类型,则直接销毁旧的,重建新的。若是相同的类型,则看下 className、style 等是否相同,同时保留不变的状态,比较完继续对子节点递归,比如列表,在设置 key 的情况下 diff 的开销会更小 (没有key的情况下,在表头插入将会重建,表尾只会添加)
Vue3 新特性
- v3 重写了 vdom,性能提高 1
2 倍,ssr 提高 23 倍。 - v3 支持 tree-shaking,原理 ?
- babel 编译的代码经过 uglifyjs 的 tree-shaking 因为函数副作用(IIFE、原型属性等影响)的原因无法真正消除所有无用的代码,而 rollup 却可以,因为它们做了程序流分析。另外静态 import 有利于 t-shaking。
- v3 Composition API 类似于 React Hooks:优势按着逻辑编程。
- v3 对象式的组件声明方式,可以更好的 TS 支持,自定义渲染器 vugel。
- v2 的 definePropterty() 实现的数据绑定无法实现数据对象新增属性值的变化,且vue中的数组方法也是自己 polyfill实现的。
- 作用域插槽改成了函数的方式,这样只会影响子组件的重新渲染,提高了性能。
- 监测机制改进了 defineProperty 的不足,另外支持 Map、Set、WeakMap 和 WeakSet。
MVC,MVVM 架构演变
MVC 相信这是绝大部分程序员最早接触到的架构。
MVVM 双向绑定:V 的变动,自动反映在 VM 上。V 和 M 不发生联系,其他部分的通信都是双向的。
MVVM 框架目前存在的问题:执行效率,数据改变, UI 也会频繁更新,引发子组件更新,性能不是最优。好消息是 Vue 3 已经解决了这个子组件重复渲染的问题,但需知没有完美的解决方案,只有舍与得。
很多人没有分清的是:ReactJs 其实是一个单向数据流的 js 库,状态驱动视图,是 MVC。而 React 全家桶是 MVP,近似 MVVM。
本身 C,P,VM 的边界界定就十分模糊,不用钻牛角尖,核心其实就是每一层专注于每一层的任务。如何对代码进行组织管理,还是要看需求来界定的,这也是框架架构模式不断发展的原因。
Vue 和 React 的区别
这一道题,可以说是上面的归总,我们可以从大到小,从略到详,从思想、生态、语法、数据、通信、Diff、版本等角度来讲,笔者整理了一些,以下挑几个重点吧...
Vue 和 React
- 生态:以 2020 年国内情况来看,可以说不分伯仲了,再看 Vue3 released on Friday, September 18, 2020,您品,您细品。
- 上手难度:显然 Vue 更易上手,Vue 的理念就是约束你、成就你。
- 架构:Vue 是 MVVM,双向绑定,依赖自动跟踪;Reactjs 是 MVC,单向数据驱动。Vue 的 v-model 本质上是 input 事件和 value 的语法糖,可以使用 props/event 自定义;React 的 setState 伪异步,更新渲染需要手动优化。
- 渲染:Vue、React 的 Diff 区别,前者是树的递归遍历、后者链表。
- ...
Vue3 和 React16 的区别
- Vue3 setup(props) 在 beforeCreate 之前
- Vue3 setup(props) props 不能解构,形如 setup({name}) 这样是错误的,会造成 watch 无法更新响应
- React16 hook 函数最顶层使用,保证顺序
- Vue3 组件选项 setup 声明周期内只被调用一次,取名就能看出来,初始化并收集依赖,数据更新就会执行依赖
- React16 hook 实际每次渲染还是执行整个函数,本质上编译方法还是 React.createElement,按顺序存储 fiber 链表,每次渲染都是按顺序取节点,所以禁止条件调用;
- React16 每次渲染,useEffect 都会重新执行并产生闭包,性能和 GC 压力上逊于 v
- React16 监听数据时,useEffect 的第二项 [] deps 会进行前后两次渲染的浅对比 Object.is
- React16 hook 闭包陷阱:假如忘记传递正确的依赖项数组,useEffect、useMemo 可能会捕获过时的变量
- Vue3 setup(props) computed watchEffect 自动跟踪依赖
- 响应原理差异
- ...
Vue3 和 React16 的相似处
- Suspense:Vue3 的 Suspense 异步嵌套比 React16 更加轻量,React16 还在完善中
- 自定义 hook:逻辑重用,不用反复横跳,返回的值自定义不用担心命名冲突……
- 创建响应式数据:Vue3 的 ref,React16 的 useState
- ...
Vue3 和 React16 总结
- React16 本身富有创造力,我们需要自己设计顺序、渲染优化
- Vue3 的 hook 灵感来源于 React16,同时响应式模式恰好解决了 React16 的问题:hook api 执行顺序、优化、追踪、闭包
- 谈谈 Vue3 抄袭:Vue3 相比 React16 有相似之处,更有超越的地方。框架本身就是给人用的,易上手也是其中重要的前提。react-router 也有借鉴 vue-router……
- ...
浏览器与网络协议
从输入到渲染的整个流程? 流程里每个部分拿出来都能深挖,我认为这道题颇有道中三生万物的韵味,前端的一切都可以从这里开始,说白了 PC 的前端是被绑定在浏览器中的。
我本人原本对于渲染的这一块,图层和合成理解并不清晰,于是将这篇放这里:为什么 CSS 动画比 JS 高效
- LCP 实时更新的最大内容绘制:2.5s 内算体验优秀,一直更新直到用户交互后停止记录,大元素的快速载入总是让人感觉网速良好。
- FID 首次输入延迟:即首次交互响应时间,记录在 FCP 和 TTI 之间用户首次与页面交互时响应的延迟,小于 100ms 为佳。补充:因为 idle 内假如有超过 50ms 的长任务,待页面响应会给人一种延迟感,综合考虑为 100ms。
- CLS (Cumulative Layout Shift) 累计位移偏移:记录了页面上非预期的位移波动,
位移距离 × 位移影响的面积 < 0.1满足这个公式便算体验优秀,反例:小屏手机上突然插入 dom 或广告让人膈应。
浏览器缓存
掌握强缓存字段,协商缓存字段。
展开:除了常规的缓存手段,还可以扩展下 1.代理缓存,2.V8 代码缓存
HTTP
这一块的内容是通过一些书籍和文章整理来的,记录了一些容易混淆的点。
首先需要理清:http2 解决性能问题;http3 解决 http2 遗留问题;https 解决安全问题。
HTTP 加密算法
-
对称加密
-
非对称加密
-
传统 RSA 握手:是
1. + 2. + 数字证书结合(在交换密钥环节使用公开密钥加密方式,建立通信交换报文阶段使用共享密钥加密方式) -
TLS1.2 握手,与
3.的区别在于pre_random的生成方式不同。 -
证书相关:
证书只解决了公钥持有人到底是谁。
原证书内容:签发者、证书用途和基本信息、服务器公钥、服务器加密算法、服务器 HASH 算法、证书的到期时间等。
原证书内容 + 最重要的防篡改的数字签名 = 服务器发给客户端的数字证书
数字签名:对原证书内容进行 hash 函数(比如 SHA256)生成的摘要 digest(摘要代表服务器身份,可以理解为身份证),经过 CA 私钥加密后生成数字签名 signature,将数字签名附在原证书末尾。这里跟 JWT 很像。
-
客户端收到数字证书,使用 CA 公钥解密 signature 得到 digest 验明身份,再使用 hash 函数对证书原数据计算,得到的结果与 digest 对比,完全一致说明数据未被修改
-
放出《图解 HTTP》原文用以确认:
服务器有自己的公钥和私钥,此时向 CA 申请证书,提交自己的公钥及基本身份信息。
CA 也有自己的公钥和私钥,...用 CA 自己的私钥...生成数字签名,同时将服务器公钥绑定入证书。这里注意:CA 公钥已经在我们安装浏览器的时候植入我们机器了。
客户端收到数字证书,先用浏览器内置的 CA 公钥解密证书的数字签名,得到 hash 后的摘要,我们假定叫做
hash_0,然后我们自己使用 hash 函数对证书内原报文进行计算,生成hash_1,两者一致即可确认服务器公钥的真实性。 -
Q:中间人是否会拦截发送假证书到客户端呢?A:因为证书的签名是由服务器端网址等信息生成的,并且通过第三方机构的私钥加密中间人无法篡改; 所以最关键的问题是证书签名的真伪。 -
还有
网络安全、4 种常见连接方式、TCP 握手和挥手、TCP 流量控制和拥塞控制、HTTP 传输各种资源的表头字段、流与分段传输 (包括上传和下载)、TCP 序列号等一堆重点。 -
扩展:
UDP 协议在游戏场景使用较多,有 DTSL 保证安全,UDP 相当于 4 层的 IP 协议,方便上层协议的自定义和扩展。
https 握手证书验证过程太耗费流量,同时因安全问题被禁止压缩,且假如把 tls 只是看成一个技术参考,是可以任意修改的,于是很多企业开始自定义内部协议,比如微信。
QUIC(Quick UDP Internet Connections)基于UDP的传输层协议,提供像TCP一样的可靠性。直播协议:RTMP、HTTP-FLV、HLS
甜品
只有严格的工序、精确的用量才能保证甜品如我们预期;只有不断改进烘焙方式和花样才能推陈出新,吸引更多顾客;只有好吃的甜品能够给人愉悦和幸福感。
严格的开发流程
完整的开发流程一般如下:
- 产品提出需求,内部领导评审。
- 内部评审通过,拉上 RD、QA、UE 等评审需求、通过后开始详细设计。
- 评审这些设计比如 RD 的技术方案如何、UI 的视觉设计怎样,其中技术评审往往会让我们对业务风险的把控、技术栈更清晰。
- 评审结束进行排期、QA 的排期根据 RD、FE的排期而定。
- 前后端分离开发配合 Mock 数据 + 联调自测。
- 资深开发进行 Code Review。
- 邮件提测 QA ,进行各种环境的测试。
- 产品验收准备上线、准备上线计划:功能点,上线顺序,回滚计划等。
- 上线后再回测。
- 第 2 次验收……
面试中/工作中看中的是 ?
-
价值:你做的东西是否有价值?价值囊括很多方面。
-
推动力:企业所希望看到的,升职加薪的必要条件。
-
社区产出:提高你的社会影响力,可能创造无限可能的未来。这一块大厂似乎很看重,有没有道友现身说法的 ?
就像简历中我们所写的:将某个项目的首屏加载提高了 x 倍,在 LCP、FID、CLS 等核心指标上又优化减少了多少秒;今天将软件运行优化得趋于原生体验;明天又产出了某个自研脚手架,提高 x 倍的开发效率;还有社区贡献,影响力...这些都是价值,或者说亮点。
价值在企业招聘中,比重很大,关乎你的未来钱途。甚至间接影响你的身体状况。
别不信,举个例子:程序员,避免不了每天面对新的需求,但是工作内容都是那样,重复又重复,如果一味莽干,免不了要加班、要秃头,占用多少自己的时间和生命?所以一个具有高价值、高优先级的东西,就是提效工具。
有些老油子可能会说:工作都那么忙了,业务需求频繁变更,哪来的时间?我只能轻蔑一笑,呵呵,时间如乳 go&%f3h,挤挤总是会有的。
一个提效工具能挽救多少业务、多少根头发,多少对情侣,相信几年之后,诸君会深有体会。
总结:优先做重要不紧急的事情:个人/团队规划、提效工具/平台建立、锻炼身体/个人影响力建立。事情是做不完的,只需要保证最重要的事情一直在被推进,不重要的可以讨论/推掉/改方案,最后还有一点,就是持续反思,反思可以让你进步飞快。
我的梦想很多,但姑且沉下心来,先实现当前这一个。
早些时候参加了个线下峰会,当时看着一群大佬轮流在台上技术分享,都是一些非常有意思的干货内容,整场下来我的状态是:吃鲸...兴奋...崇拜...
这就是前端吗 ?i 了 i 了,于是额前绑上奋斗的 “奋”,一头莽进了这行。
转眼 0202!
入行这几年,大部分时光都是平淡无奇的,我本来就是个平凡、温和、闷骚、咸鱼的人……常驻知乎、掘金等社区却一直潜水不起一点波纹。
某个时刻,我阅读到 神三元 的系列文章,起初觉得干货满满,嗯,这是个大佬,关注了,每次阅读完他的文章我都淡定地喝一口茶,感觉获益良多。
疫情期间,他又有产出,我照例翻出一览,良久,我喝了口茶,随后眉头一皱,顿觉不对,看下标题,春招?……噗!我震惊,不确定,然后欣喜,沮丧……
这!这居然是一个大三学生,我 &$%^@,大三就进了字节互娱架构组,了不起,恭喜你……
没有比较就没有伤害,想想自己……emmm,原来我是个假前端!
神三元早早就明确了未来目标,就像他文章中说的,找到了痛点。而我们大多数人直到工作了,还很迷茫。就像女生刷 Fit 视频,看到视频里的健身达人曲线姣好的身材,羡慕不已。但看完视频,却只是简单地在床上翻了个身给予回应,甚至还照常打开某团点了杯奶茶。
呵呵,我不想再这样了,现在,先完成 那个 目标吧!
写给未来的我和你们……