2020前端知识储备
2020前端基础知识
适用于20/21届前端同学
基础
JavaScript基础
常用设计模式
- 装箱 / 拆箱 & 类型转换
在JavaScript里面有个引用类型叫做基本包装类型,它包括String、Number和Boolean。那么它和基本的类型String、Number和Boolean是啥关系呢?接着往下看?
装箱操作
所谓的装箱,是指将基本数据类型转换为对应的引用类型的操作。而装箱又分为隐式装箱和显式装箱。
①隐式装箱
对于隐式装箱,我们看下下面的代码:
var s1 = 'call_me_R'; // 隐式装箱
var s2 = s1.substring(2);
上面代码的执行步骤其实是这样的:
创建String类型的一个实例;
在实例中调用制定的方法;
销毁这个实例。
上面的三个步骤转换为代码,如下:
var s1 = new String('call_me_R');
var s2 = s1.substring(2);
s1 = null;
隐式装箱当读取一个基本类型值时,后台会创建一个该基本类型所对应的基本包装类型对象。在这个基本类型的对象上调用方法,其实就是在这个基本类型对象上调用方法。这个基本类型的对象是临时的,它只存在于方法调用那一行代码执行的瞬间,执行方法后立即被销毁。这也是在基本类型上添加属性和方法会不识别或报错的原因了,如下:
var s1 = 'call_me_R';
s1.job = 'frontend engineer';
s1.sayHello = function(){
console.log('hello kitty');
}
console.log(s1.job); // undefined
s1.sayHello(); // Uncaught TypeError: s1.sayHello is not a function
②显式装箱
装箱的另一种方式是显示装箱,这个就比较好理解了,这是通过基本包装类型对象对基本类型进行显示装箱,如下:
var name = new String('call_me_R');
显示装箱的操纵可以对new出来的对象进行属性和方法的添加啦,因为通过通过new操作符创建的引用类型的实例,在执行流离开当前作用域之前一直保留在内存中。
var objStr = new String('call_me_R');
objStr.job = 'frontend engineer';
objStr.sayHi = function(){
console.log('hello kitty');
}
console.log(objStr.job); // frontend engineer
objStr.sayHi(); // hello kitty
③拆箱操作
拆箱就和装箱相反了。拆箱是指把引用类型转换成基本的数据类型。通常通过引用类型的valueOf()和toString()方法来实现。
在下面的代码中,留意下valueOf()和toString()返回值的区别:
var objNum = new Number(64);
var objStr = new String('64');
console.log(typeof objNum); // object
console.log(typeof objStr); // object
# 拆箱
console.log(typeof objNum.valueOf()); // number 基本的数字类型,想要的
console.log(typeof objNum.toString()); // string 基本的字符类型,不想要的
console.log(typeof objStr.valueOf()); // string 基本的数据类型,不想要的
console.log(typeof objStr.toString()); // string 基本的数据类型,想要的
-
常用位运算
-
原型
- __proto__与prototype
- Object.prototype
- Function与Object
-
闭包
- 实现
- 应用
- 原理
- 经典问题(
setTimeoutIIFElet)
-
执行上下文 调用栈 作用域链
- 变量对象(VO)与活动对象(AO)
-
继承
- 寄生组合式继承(组合+原型)
-
事件循环
- 浏览器UI渲染与事件循环?
- async与await
- Promise/A+规范
- 立即resolved的Promise执行时机
-
垃圾收集
- 标记清除
- 引用计数
- 循环引用如何处理?
-
this
- 作用 & 意义
- this指向
- 隐式丢失
- 优先级
- 箭头函数的this
(一)一般情况
函数中的this基本都指向函数的调用者。
function demo1(){
console.log(this)
}
var demo2 = {
log() {
console.log(this)
}}
var demo3= {
log() {
setTimeout(function print(){ // 给一个函数名方便理解
console.log(this)
},1000)
}
}
demo1() // window;
demo2.log() // {log: f};
demo3.log() // window;
①demo1(): 可以理解成window.demo1() 所以调用者是window, this =window
②demo2.log(): log方法的调用者是demo2 所以this=demo2
③demo3.log(): 本示例中print方法作为参数传给了setTimeout方法,所以在调用demo3.log()时并未执行该方 法,而是在1s的延时之后执行了print这是调用者又变成了window 所以this=window
(二)既然有一般情况,肯定也有非一般的情况。
// 第一种:new (作为构造函数调用)
function Demo() {
this.a = 1;
console.log(this)
}
new Demo() // {a: 1}
// 第二种:apply、call
function log() {
console.log(this, arguments)
}
var target = {a: 1}
log.apply(target, [1,2,3]) // {a:1} [1,2,3]
log.call(target, 1, 2, 3) // {a:1} [1,2,3]
// 第三种:bind、箭头函数
log.bind(target)
log(1, 2, 3) // {a:1} [1,2,3]
// 使用之前的demo3做示例
var demo3= {
log() {
setTimeout((function print() {
console.log(this)
}).bind(this), 1000)
// 等同于 setTimeout(() => console.log(this), 1000)
}
}
demo3.log() // {log: f}
①使用new关键字调用函数时会先声明一个新的对象然后将函数中的this指这个新的对象,所以例子中可以理解成先执行了this ={}然后再执行之后的内容
②apply、call是两个常用的改变函数this指向的方法,他们的第一个参数是替换this的对象可以理解成先执行了this =target,区别在于第二个参数。apply的第二个参数是一个数组这个数组会拆一个个参数传入函数([1,2,3]会变成log(1,2,3)),而call会将第二个及之后的参数作为函数的参数传入函数
③bind和箭头函数其实是一种方式(箭头函数其实是一种语法糖简化了bind写法), 由于现在箭头函数用的比较多所以放在一起说下。bind方法的作用是绑定函数的作用域但是不会立即执行这个函数,这也更符我们的使用场景。我们改写了demo3的实现,在声明print方法的同时使用bind方法绑定了this。当我们调用demo3.log时,这时this指向调用者demo3,所以bind中的this就是demo3,即使延时了1s执行this指向也不会因为调用者的改而改变
- 对象冻结
- freeze
- seal
- Object.defineProperties() 与 descriptor
- 模块化
- ES Modules与CommonJS差异
- 对循环引用的处理
- 其他
- caller / callee
- typeof 与 Instanceof 原理
- tyoeof null? (机器码)
- 柯里化
- 尾递归
- 类数组
- isNaN 和 Number.isNaN
- Obejct.is()漏洞
- React 使用的
shallowEqual()对其进行的增强
- React 使用的
HTML&CSS
-
语义化
-
SEO
-
DTD
<!DOCTYPE> -
W3C与WHATWG
-
Html5新增API
-
DOM/BOM API
-
常见布局
-
优先级
-
伪类与伪元素
-
预处理器与后处理器
-
盒模型
-
CSS3动画
- GPU加速原理
-
定位
-
文档流
-
sticky
-
-
src & href
-
Flex
-
Grid
-
Rem与em
-
Flexible.js思路
-
BFC / IFC
-
水平 / 垂直 / 水平垂直居中
-
Prefix
-
reset与normalize.css
-
移动端
-
像素比
-
检测横屏
-
图片模糊问题
-
IOS橡皮筋问题
-
视口类型
-
Vw Vh
-
1Px
-
基础手写/算法
-
ajax
-
bind / call / apply
-
debounce / throttle
-
instanceof
-
深浅拷贝
-
promise
-
lazy man
-
new
-
用setTimeout实现setInterval
-
继承
- 实现ES6 Class实质的继承
-
冒泡 / 快排 / 选择 ...
-
观察者与发布订阅模式
ES6
-
ES6的Class实质, 与ES5继承异同?
- Babel编译结果
- 为什么先
super()?
-
Generator
- 协程
- yield
- co模块
- Thunk函数
-
Iterator
- for...of
-
Symbol
- 常用的内置接口
-
ES6 Module与CommonJS
-
Promise
- 回调函数延迟绑定
- 错误穿透
- 状态机制
-
Async/Await 的原理
-
Decorator
-
Proxy
- 为什么Vue抛弃了Object.defineProperty
- 元编程
- 常用方法
-
Reflect
- 为什么需要它?
- 与Proxy的结合
-
map set
-
map与对象互转
-
set与数组互转
-
weakMap weakSet
-
-
其他新增API
-
关于TC39的标准制定过程
- Strawman
- Proposal
- Draft
- Canidate
- Finished
-
ES 7/8/9/10 /...
- 可选链
- null判断
- 私有变量
- ...
Node
-
优缺点 适用场景
-
Node创建子进程的方式
- spawn
- exec
- execFile
- fork
-
npm install
- dedupe
-
Buffer
-
Stream
-
Node的适用场景及原因
-
V8内存管理
- 新生代与老生代机制
- From空间与To空间
- 标记清除与标记整理
- 触发点
- 增量标记
- 新生代与老生代机制
-
Cluster & IPC
- child_progress
- 主从模式
-
Node异步I/O & 进程池 & Libuv
-
事件循环
- timer
- I/O
- Idle prepare
- poll
- 阻塞
- check
- close CB
- 每一阶段均有的nextTick与microTask
-
Koa
-
vs Express?
-
中间件原理 与 洋葱模型
-
浏览器
-
跨域与跨站
-
强缓存与协商缓存
-
优先级
-
请求与响应中的缓存相关请求头
-
E-tag 与 Last-Modified
-
-
从输入URL到页面呈现
-
页面渲染中的不良现象
- 白屏
- FOUC
-
图层树 绘制指令 绘制列表
- 显示提升
- 隐式提升(层爆炸)
-
栅格化线程池 位图
-
重绘 回流
-
DOM树与CSSOM树建树过程
- 令牌化->建树
- 样式收集
-
阻塞
- js & dom
- css & js
- async & defer
-
-
操作DOM为什么慢
- 互斥
-
cookie / session / token
- Chrome80默认cookie samesite属性为Lax, 造成的影响?
- 如何解决兼容性
- 双令牌机制
- cookie session_id
- jwt机理
- Chrome80默认cookie samesite属性为Lax, 造成的影响?
-
本地存储
-
service worker
-
requesAnimationFrame
-
requestIdleCallback
-
事件机制
- 委托发生的阶段
- IE的事件模型
- 阻止事件与冒泡
- addEventListener & useCapture
-
RESTFul规范
-
跨域
- JSONP 原理
- Nginx 原理
- CORS
- Options预检
- 简单 / 复杂 请求
- 相关字段
-
前端路由原理
- hash
- onHashChange
- history
- pushState
- replaceState
- onPopState
- hash
-
XSS
- 文档型 & 反射型 & 存储型
- httpOnly
- 转义
- CSP
-
XSRF
-
GET型 POST型 链接类型
-
同源检测
- origin
- referer
-
axios的XSRF防御手段
-
samesite
-
-
Fetch & XHR对比
- cookie
- abort
- onProgress
数据库
- 脏读 / 幻读 / 不可重复读
- 事务及边界
- 索引
网络
- 七层与五层模型
- DNS查找机制
- CDN CNAME
- http1.1 -> http1
- 身份认证
- 断点续传(206状态码)
- 缓存
- keep-alive
- http2 -> http1.1
- 多路复用
- 头部压缩
- server-push
- https 会话层机制?
- 浏览器内置CA链
- TCP 握手/挥手 过程中出错?
- 泛洪攻击
- RST包
- TCP/UDP适用场景
- QUIC协议
- 为什么DNS使用UDP
- TCP拥塞控制
- 慢启动 & 拥塞避免
- 快速重传 & 快速恢复
- 正向代理与反向代理
- Get与Post区别
- 幂等性
进阶
框架及工具
TypeScript
- type & interface
- 泛型
- 工具类型
- 类型守护
- 装饰器 / IOC
Git
- git fetch
- git rebase
- git merge
- git reset
- hard
- soft
- mixed
- git revert
Webpack & Parcel
- compiler与compilation
- HMR原理
- 工作流程
- Loader
- 以Babel-Loader为例
- Plugin
- 事件流模型
- 性能调优
- 打包速率
- 打包大小
- 打包交互友好度
- 异同
React
-
Immutable.JS
-
生命周期
- WillMount x
- render
- DidMount
- 为什么数据获取要在这里? 而不是WillMount?
- WillReceiveProps x
- shouldComponentUpdate
- WillUpdate x
- render
- DidUpdate x
- 以下为新增
- getDerivedStateFromProps
- getSnapshotBeforeUpdate
- getDerivedStateFromError
- 与componentDidCatch如何搭配
-
为什么要废弃掉这几个生命周期?
- 为什么getDerivedStateFromProps是静态方法
-
Hooks
-
useEffect
-
useState
-
forwardRef & useRef & useImperativeHandle
-
-
Fiber
-
requestIdleCallback
-
机制
-
reconciliation / commit
-
-
Redux
- 中间件原理
-
setState
- 原生事件->同步, 合成事件->异步, 为什么?
-
React实现的事件机制
-
V-Dom与Diff
- 时间复杂度
-
与Vue的比较
- 约束 / 迎合
- 思想
Vue
- MVVM原理
- Observer
- Compile
- Watcher
业务场景
- 白屏问题排查
- 骨架屏
- 超长列表
- requesAnimationFrame
- 虚拟列表
- 单点登录(SSO)
- 埋点的原理
- 扫码登陆
- 大文件分片/完整性校验/断点续传/秒传/拖拽上传/粘贴上传
小程序
-
基础架构
-
properties / data
-
behavior
-
DOM BOM如何禁止访问的?
-
生命周期
-
性能优化
-
vs PWA / H5 / Hybrid / 各种跨端方案
漫谈
测试
- 单元测试
- E2E
- 混沌
工程化
-
错误监控
-
性能优化
-
脚手架
-
埋点
- SPA应用
- Hybrid应用
-
GraphQL & BFF & Apollo
- vs RESTFul 优劣势
- BFF意义, 解决了什么问题?
- 接口清洗 聚合 ...
- 带来的新问题
- Serverless协作
- Apollo生态圈的主要package
-
CI / CD, 自动化构建流程解决了什么问题?
-
Serverless
- FaaS
- BaaS
- 小程序云函数思路
-
前端趋势
- 智能化
- 跨端
- 5G 物联网
- Flutter 与 RN此类方案
- 演进
- 价值
- 向后端侵袭
- 对业务更熟悉
-
工程化
- 模块化
- 以React为例, 你的组件模块化思路?
- 项目开发模块化
- 规范化
- 各种各样的Lint
- CR
- 测试
- ...
- 系统化
- 微服务
- Serverless
- 中间层
- ...
- 模块化

浙公网安备 33010602011771号