JavaScript基础
变量和类型
-
JavaScript规定了几种语言类型
- Undefined
- Null
- String
- Number
- Boolean
- Symbol
- Object
-
JavaScript对象的底层数据结构是什么
- Object -> HeapObject -> JSReceiver -> JSObject: JSArray, JSFunction, JSCollection(Set, Map)等
-
Symbol类型在实际开发中的应用、可手动实现一个简单的Symbol
- 应用
- 替代常量
- 作为属性名
- 定义枚举值
- 应用
-
JavaScript中的变量在内存中的具体存储形式
- 栈内存: 基础类型
- 堆内存: 引用类型
-
基本类型对应的内置对象,以及他们之间的装箱拆箱操作
- 装箱: 基础类型 -> 引用类型; new Number, new String, new Boolean
- 拆箱: 引用类型 -> 基础类型; valueOf, toString
-
理解值类型和引用类型
- 值类型
- 占用空间固定, 栈内存中
- 保存和复制值本身
- typeof
- 引用类型
- 占用空间不固定, 堆内存中
- 保存和复制一个指针
- instanceof
- 值类型
-
null和undefined的区别
- null: 表示对象为空
- 作为函数参数, 表单参数为空
- 对象原型链终点
- 转为数字为0
- undefined: 表示值为空
- 形参未传递, 值为undefined
- 对象属性名不存在, 属性值为undefined
- 函数没有return, 返回值为undefined
- 转为数字为NaN
- null: 表示对象为空
-
至少可以说出三种判断JavaScript数据类型的方式,以及他们的优缺点,如何准确的判断数组类型
- typeof
- instanceof
- {}.toString.call
-
可能发生隐式类型转换的场景以及转换原则,应如何避免或巧妙应用
- 场景
- if语句: Boolean
- 减,乘,除: Number
- 加
- 一侧String: String
- 一侧Number, 另一侧为原始类型: Number
- 一侧Number, 另一侧为引用类型: 转字符串后拼接
- 对象转数字: valueOf() -> toString() -> 抛错
- 场景
-
出现小数精度丢失的原因,JavaScript可以存储的最大数字、最大安全数字,JavaScript处理大数字的方法、避免精度丢失的方法
- 小数精度丢失的原因
- 浮点数运算
- 大整数运算
- toFixed五不会入
- 最大数字: Number.MAX_VALUE
- 最大安全数字: Number.MAX_SAFE_INTEGER
- 处理大数字方法
- 转字符
- BigInt
- 第三方库
- 小数精度丢失的原因
原型和原型链
-
理解原型设计模式以及JavaScript中的原型规则
-
instanceof的底层实现原理,手动实现一个instanceof
function _instanceof(Fn, inst) {
let proto = inst.__proto__;
while (proto) {
if(proto === Fn.prototype) {
return true;
}
proto = proto.__proto__;
}
return false;
}
-
实现继承的几种方式以及他们的优缺点
- 原型链继承
- 构造函数继承
- 组合继承
- extends
-
至少说出一种开源项目(如Node)中应用原型继承的案例
-
可以描述new一个对象的详细过程,手动实现一个new操作符
function _new(Fn, ...args) {
const inst = {};
inst.__proto__ = Fn.prototype;
const res = Fn.call(inst, ...args);
return typeof res === 'object' ? res : inst;
}
- 理解es6 class构造以及继承的底层实现原理
- 构造: 构造函数
- 继承:
subClass.prototype.__proto__ = superClass.prototype; // 静态方法 subClass.__proto__ = superClass;
作用域和闭包
-
理解词法作用域和动态作用域
- 词法作用域: 函数声明时确定
- 动态作用域: 函数调用时确定; js没有动态作用域, this机制有点像
-
理解JavaScript的作用域和作用域链
- 全局作用域: Global, Script
- 局部作用域: Local, Block
- 作用域链: 从最前端作用域一层层往上检索标识符的过程
-
理解JavaScript的执行上下文栈,可以应用堆栈信息快速定位问题
- 执行上下文栈
- 全局
- 函数
- eval函数
- 上下文生命周期
- 创建
- 执行
- 回收
- 执行上下文栈
-
this的原理以及几种不同使用场景的取值
this是一种动态绑定, 取决于如何调用函数
- 默认: window
- 隐式: 对象方法调用
- 显式: call, apply, bind
- new: 生成的新对象
- 箭头函数: 当前上下文
-
闭包的实现原理和作用,可以列举几个开发中闭包的实际应用
- 概念: 函数和其引用的外部变量
- 作用: 保持外部变量一直存在
- 应用
- 函数作为返回值
- 函数作为参数
- 立即执行函数
-
理解堆栈溢出和内存泄漏的原理,如何防止
- 堆栈溢出: 内存被申请完
- 内存泄露: 申请的内存没有及时回收
- 防止
- 避免全局变量
- 避免对象循环引用
- 及时关闭定时器
- 及时释放DOM引用
- 及时释放事件
- 合理闭包
-
如何处理循环的异步操作
- await
- 递归
-
理解模块化解决的实际问题,可列举几个模块化方案并理解其中原理
- 解决问题
- 命名空间冲突
- 文件依赖管理
- 方案
- commonjs
- amd
- esm
- 解决问题
执行机制
-
为何try里面放return,finally还会执行,理解其内部机制
- try里面的代码报错的时候,catch里面的代码才会执行,finally里面的代码永远会执行
- catch和finally里面,正常的代码会从上到下顺序执行
- 如果只是catch里面代码出错,则报catch里面的错误
- 如果catch和finally都出错则会报finally里面的错误
-
JavaScript如何实现异步编程,可以详细描述EventLoop机制
- 异步编程
- Promise
- async/await
- Generator
- callback
- 事件监听
- 发布/订阅
- 异步编程
-
宏任务和微任务分别有哪些
- 宏任务: script代码, setTimeout, setInterval
- 微任务: Promise.then, MutationObserver(浏览器), process.nextTick(node)
-
可以快速分析一个复杂的异步嵌套逻辑,并掌握分析方法
-
使用Promise实现串行
- async/await + 循环
-
Node与浏览器EventLoop的差异
- node11+: 与浏览器一致
- node10-: 执行完同级所有宏任务, 再执行同级所有微任务
-
如何在保证页面运行流畅的情况下处理海量数据
- 分次加载
- 虚拟列表
语法和API
-
理解ECMAScript和JavaScript的关系
- ECMAScript是语言规范
- JavaScript是规范的实现
-
熟练运用es5、es6提供的语法规范,
-
熟练掌握JavaScript提供的全局对象(例如Date、Math)、全局函数(例如decodeURI、isNaN)、全局属性(例如Infinity、undefined)
-
熟练应用map、reduce、filter 等高阶函数解决问题
-
setInterval需要注意的点,使用settimeout实现setInterval
- 注意: 多次启动时, 需关闭前一次定时器
function _setInterval(fn, timeout = 300) {
function inner() {
fn();
setTimeout(inner, timeout);
}
inner();
}
-
JavaScript提供的正则表达式API、可以使用正则表达式(邮箱校验、URL解析、去重等)解决常见问题
-
JavaScript异常处理的方式,统一的异常处理方案
HTML和CSS
HTML
-
从规范的角度理解HTML,从分类和语义的角度使用标签
- 语义化
- 结构清晰
- 屏幕阅读器, 无障碍
- SEO权重
- 维护性
- 分类
- 文档: html, head, body
- 表格: table, td
- 表单: input, form, button, select
- 列表: ul, li
- 多媒体: video, audio
- 文章: h1-6, p
- 字体: b, i
- 语义化
-
常用页面标签的默认样式、自带属性、不同浏览器的差异、处理浏览器兼容问题的方式
-
元信息类标签(head、title、meta)的使用目的和配置方法
-
HTML5离线缓存原理
通过manifest解析离线存储资源, 然后存储在浏览器中; 当网络离线时, 浏览器可直接读取已存储资源
-
可以使用Canvas API、SVG等绘制高性能的动画
CSS
-
CSS盒模型,在不同浏览器的差异
- margin
- border
- padding
- content
content不包含其他部分, IE为border-box
-
CSS所有选择器及其优先级、使用场景,哪些可以继承,如何运用at规则
- 优先级: !import > id > class > tag > * > inherit > useragent
- 位置: 行内 > 内联 > 外部 > @import;
- 可继承属性:
- 字体系列: font
- 文本系列: text-align, line-height, color
- visibility, cursor
- at-rules
- @charset
- @import
- @namespace
- @media, @font-face, @keyframes, @page, @suports, @document
-
CSS伪类和伪元素有哪些,它们的区别和实际应用
- 伪类: :active, :focus, :hover, :first-child
- 伪元素: :before, :after, :first-line, :first-letter
- 区别: 伪元素创造新的显示元素, 伪类没有
-
HTML文档流的排版规则,CSS几种定位的规则、定位参照物、对文档流的影响,如何选择最好的定位方式,雪碧图实现原理
- 排版规则: 从上到下, 从左到右
- 定位规则: static, float, relative, absolute, fixed
-
水平垂直居中的方案、可以实现6种以上并对比它们的优缺点
- text-align: center, line-height
- table-cell
- flex, justify-content: center; align-items: center;
- absolute, left: 50%; top: 50%; 负margin
- absolute, left: 50%; top: 50%; translate(-50%,-50%)
- grid, justify-self: center; align-self: center;
-
BFC实现原理,可以解决的问题,如何创建BFC
-
可使用CSS函数复用代码,实现特殊效果
- attr()
- calc()
- rgba()
- var()
- linear-gradient()
-
PostCSS、Sass、Less的异同,以及使用配置,至少掌握一种
-
CSS模块化方案、如何配置按需加载、如何防止CSS阻塞渲染
- 模块化: 文件命名约定, CSS Modules
- 媒体查询: link的media属性
- 防止阻塞: 非首屏CSS异步加载
-
熟练使用CSS实现常见动画,如渐变、移动、旋转、缩放等等
-
CSS浏览器兼容性写法,了解不同API在不同浏览器下的兼容性情况
-
掌握一套完整的响应式布局方案
- rem
- 媒体查询
手写
-
手写图片瀑布流效果
-
使用CSS绘制几何图形(圆形、三角形、扇形、菱形等)
-
使用纯CSS实现曲线运动(贝塞尔曲线)
-
实现常用布局(三栏、圣杯、双飞翼、吸顶),可是说出多种方式并理解其优缺点
计算机基础
编译原理
-
理解代码到底是什么,计算机如何将代码转换为可以运行的目标程序
- 程序员按语言规范写出来的源文件
- 编译器
-
正则表达式的匹配原理和性能优化
- 优化: 减少回溯;
- 正确边界匹配器
- 不使用通配符
- 正确的量词
- 非捕获组,原子组
- 优化: 减少回溯;
-
如何将JavaScript代码解析成抽象语法树(AST)
- 词法分析: 代码 -> 词法单元
- 语法分析: 词法单元 -> 语法结构数
-
base64的编码原理
- 每3个字符为一组, 占24位
- 将24位分成4组, 每组占6位
- 每组前加2个0, 得到一个数
- Base64编码对照表, 将数字映射为字符
不够位的用 = 补位
-
几种进制的相互转换计算方法,在JavaScript中如何表示和转换
- parseInt(str, radix)
- number.toString(radix)
网络协议
-
理解什么是协议,了解TCP/IP网络协议族的构成,每层协议在应用程序中发挥的作用
- 协议: 通信计算机双方共同遵从的约定
-
三次握手和四次挥手详细原理,为什么要使用这种机制
-
有哪些协议是可靠,TCP有哪些手段保证可靠交付
-
DNS的作用、DNS解析的详细过程,DNS优化原理
- 作用: 将域名与IP相互映射
- 过程: 缓存查找的过程
- 优化: 减少域名, dns-prefetch
-
CDN的作用和原理
- 传输更快,更稳定
- 多域名
- 缓存
- 分布式
-
HTTP请求报文和响应报文的具体组成,能理解常见请求头的含义,有几种请求方式,区别是什么
- 请求报文
- 请求行: GET url HTTP/1.1
- 请求头
- 空行
- 请求体
- 响应报文
- 响应行: HTTP/1.1 200 OK
- 响应头
- 响应体
- 请求头
- accept
- content-length
- referer
- cookie
- user-agent
- 请求方式
- GET
- POST
- PUT
- DELETE
- OPTIONS
- HEAD
- CONNECT
- TRACE
- 请求报文
-
HTTP所有状态码的具体含义,看到异常状态码能快速定位问题
- 1xx: 通知状态
- 100 Continue: 继续
- 2xx: 成功状态
- 200 OK: 正常返回
- 201 Created: 请求成功服务器创建新的资源
- 202 Accepted: 服务器已接受请求, 但尚未处理
- 3xx: 重定向
- 301 Moved Permanently: 永久重定向
- 302 Moved Temporarily: 临时重定向
- 303 See Other: 返回响应文档URI
- 304 Not Modified: 未修改过
- 4xx: 客户端错误
- 400 Bad Request: 服务器无法理解的请求
- 401 Unauthorized: 请求未授权
- 403 Forbidden: 禁止访问
- 404 Not Found: 未找到资源
- 409 Conflict: 请求导致服务器不一致
- 5xx: 服务器错误
- 500 Internal Server Error: 服务器内部错误
- 502 Bad Gateway: 代理问题
- 503 Service Unavailabel: 服务不可用
- 1xx: 通知状态
-
HTTP1.1、HTTP2.0带来的改变
- http1.1
- keep-alive: 连接不断开, 多次请求
- 支持断点续传: range请求头
- 优化缓存协议: etag, cache-control
- 支持host头
- http2.0
- 二进制分帧
- 多路复用
- 头部压缩
- 服务器推送
- http1.1
-
HTTPS的加密原理,如何开启HTTPS,如何劫持HTTPS请求
- 原理
- 握手: 非对称加密
- 握手之后: 对称加密
- 握手过程
- client hello
- 支持的SSL版本
- 支持的加密套件列表
- 随机数, 用于生成"对话密钥"
- 支持的压缩算法
- server hello
- 确认使用的SSL版本
- 确认使用的加密套件
- 服务器证书(含公钥)
- 随机数, 用于生成"对话密钥"
- client key exchange
- 对话密钥(3个随机数+服务器公钥加密)
- 编码改变通知
- client hello
- 开启
- 申请证书
- 部署证书
- 启用https
- 劫持
- 截获客户端与服务器通信的通道
- 然后在 SSL 建立连接的时候,进行中间人攻击
- 将自己伪装成客户端,获取到服务器真实有效的 CA 证书(非对称加密的公钥)
- 将自己伪装成服务器,获取到客服端的之后通信的密钥(对称加密的密钥)
- 有了证书和密钥就可以监听之后通信的内容了
- 原理
-
理解WebSocket协议的底层原理、与HTTP的区别
-
区别
- 持久化协议
设计模式
-
熟练使用前端常用的设计模式编写代码,如单例模式、装饰器模式、代理模式等
- 单例
- 观察者
- 发布/订阅
-
发布订阅模式和观察者模式的异同以及实际应用
发布/订阅有一个事件调度中心
-
可以说出几种设计模式在开发中的实际应用,理解框架源码中对设计模式的应用
- vue的响应式实现
数据结构和算法
JavaScript编码能力
- 多种方式实现数组去重、扁平化、对比优缺点
// 去重1
function uniqArray(array) {
return [...new Set(array)];
}
// 去重2
function uniqArray(array) {
const res = [];
array.forEach((item) => {
if(res.indexOf(item) === -1) {
res.push(item);
}
});
return res;
}
// 扁平化1
function flatArray(array) {
return array.flat(Infinity);
}
// 扁平化2
function flatArray(array) {
const res = [];
array.forEach((item) => {
if(Array.isArray(item)) {
res.push(...flatArray(item));
}
else {
res.push(item);
}
});
return res;
}
- 多种方式实现深拷贝、对比优缺点
// 深拷贝1
function deepCopy(object) {
return JSON.parse(JSON.stringify(object));
}
// 深拷贝2
function deepCopy(object) {
let res;
// 引用类型
if(typeof object === 'object') {
// 数组
if(Array.isArray(object)) {
res = [];
object.forEach((item) => res.push(deepCopy(item)));
}
// 对象
else if({}.toString.call(object) === '[object Object]') {
res = {};
for(const p in object) {
res[p] = deepCopy(object[p]);
}
}
// 其他
else {
res = object;
}
}
// 基本类型
else {
res = object;
}
return res;
}
- 手写函数柯里化工具函数、并理解其应用场景和优势
function curry(fn, ...curryArgs) {
return (...args) => {
const newArgs = [...curryArgs, ...args];
// 参数数量不足
if(newArgs.length < fn.length) {
return curry(fn, ...newArgs);
}
else {
return fn(...newArgs);
}
};
}
function multi (a, b, c) {
return a * b * c;
}
var multiCurry = curry(multi, 2, 3);
console.log(multiCurry(9));
- 手写防抖和节流工具函数、并理解其内部原理和应用场景
// 防抖: 多次调用, 运行1次
function debounce(fn, timeout = 300) {
clearTimeout(fn._tid);
fn._tid = setTimeout(fn, timeout);
}
// 节流: 多次调用, 每个时间间隔运行1次
function throttle(fn, timeout = 300) {
if (fn._pending) {
return;
}
fn();
fn._pending = true;
setTimeout(() => {
fn._pending = false;
}, timeout);
}
- 实现一个sleep函数
function sleep(timeout) {
return new Promise((resolve) => {
setTimeout(resolve, timeout);
});
}
sleep(3000).then(() => {
console.log('3000ms后执行');
});
手动实现前端轮子
- 手动实现call、apply、bind
Function.prototype._call = function(context, ...args) {
context = context || window;
context._fn = this;
const res = context._fn(...args);
delete context._fn;
return res;
}
Function.prototype._bind = function(context, ...args) {
const fn = this;
return function F(...curArgs) {
// 构造函数调用
if(this instanceof F) {
return new fn(...args, ...curArgs);
}
return fn.call(context, ...args, ...curArgs);
}
}
- 手动实现符合Promise/A+规范的Promise、手动实现async await
class _Promise {
constructor(init) {
}
}
- 手写一个EventEmitter实现事件发布、订阅
class EventEmitter {
}
-
可以说出两种实现双向绑定的方案、可以手动实现
- defineProperty
- Proxy
-
手写JSON.stringify、JSON.parse
-
手写一个模版引擎,并能解释其中原理
-
手写懒加载、下拉刷新、上拉加载、预加载等效果
数据结构
-
理解常见数据结构的特点,以及他们在不同场景下使用的优缺点
-
理解数组、字符串的存储原理,并熟练应用他们解决问题
-
理解二叉树、栈、队列、哈希表的基本结构和特点,并可以应用它解决问题
-
了解图、堆的基本结构和使用场景
算法
-
可计算一个算法的时间复杂度和空间复杂度,可估计业务逻辑代码的耗时和内存消耗
-
至少理解五种排序算法的实现原理、应用场景、优缺点,可快速说出时间、空间复杂度
-
了解递归和循环的优缺点、应用场景、并可在开发中熟练应用
-
可应用回溯算法、贪心算法、分治算法、动态规划等解决复杂问题
-
前端处理海量数据的算法方案
运行环境
浏览器API
-
浏览器提供的符合W3C标准的DOM操作API、浏览器差异、兼容性
-
浏览器提供的浏览器对象模型(BOM)提供的所有全局API、浏览器差异、兼容性
- location
- history
- navigator
- window
- screen
-
大量DOM操作、海量数据的性能优化(合并操作、Diff、requestAnimationFrame等)
- 使用createDocumentFragment
- 使用innerHTML
- dom渲染使用requestAnimationFrame进行优化
-
浏览器海量数据存储、操作性能优化
-
DOM事件流的具体实现机制、不同浏览器的差异、事件代理
-
前端发起网络请求的几种方式及其底层实现、可以手写原生ajax、fetch、可以熟练使用第三方库
-
浏览器的同源策略,如何避免同源策略,几种方式的异同点以及如何选型
-
浏览器提供的几种存储机制、优缺点、开发中正确的选择
- cookie
- localStorage/sessionStorage
- IndexedDB
-
浏览器跨标签通信
- onstorage
- websocket
- 定时器 + 存储数据
- SharedWorker
浏览器原理
-
各浏览器使用的JavaScript引擎以及它们的异同点、如何在代码中进行区分
- IE: Chakra
- chrome: v8
- safari: javascript core
- firefox: Spidermonkey
-
请求数据到请求结束与服务器进行了几次交互
-
可详细描述浏览器从输入URL到页面展现的详细过程
-
浏览器解析HTML代码的原理,以及构建DOM树的流程
- 标签解析: 标记化算法;
- 数据状态
- 标记打开状态
- 标记名称状态
- 标记关闭状态
- DOM树构建
- DOM树
- 一个存放标签名的栈
- 标签解析: 标记化算法;
-
浏览器如何解析CSS规则,并将其应用到DOM树上
- 选择器从右到左
- 样式叠加或覆盖
-
浏览器如何将解析好的带有样式的DOM树进行绘制
-
浏览器的运行机制,如何配置资源异步同步加载
-
浏览器回流与重绘的底层原理,引发原因,如何有效避免
- 重排
- 添加/删除DOM元素
- 元素位置改变
- 元素尺寸改变
- 元素内容改变
- 浏览器容器尺寸改变
- 页面渲染初始化layout
- 最小化重排/重绘
- 合并多次DOM操作
- 合并多次样式操作
- 先将元素display: none, 进行多次操作, 再恢复显示
- 需要重排获取到的样式属性, 储存下来
- 使用离线DOM, 如: document fragment
- 绝对定位
- 使用visibility
- 使用requestAnimationFrame重新渲染
- 动画使用transform
- 重排
-
浏览器的垃圾回收机制,如何避免内存泄漏
- 标记清除法
-
浏览器采用的缓存方案,如何选择和控制合适的缓存方案
-
Service Worker
-
Memory Cache
-
Disk Cache
-
Push Cache
Node
-
理解Node在应用程序中的作用,可以使用Node搭建前端运行环境、使用Node操作文件、操作数据库等等
-
掌握一种Node开发框架,如Express,Express和Koa的区别
-
熟练使用Node提供的API如Path、Http、Child Process等并理解其实现原理
-
Node的底层运行原理、和浏览器的异同
- V8解析js
- 解析后的代码调用Node API
- libuv负责Node API的执行, 分配不同的线程, 形成一个Event Loop, 异步将执行结果返回给V8
- V8将结果返回给应用层
-
Node事件驱动、非阻塞机制的实现原理
就是事件循环
框架和类库
TypeScript
-
理解泛型、接口等面向对象的相关概念,TypeScript对面向对象理念的实现
- 泛型: 使用的时候才决定类型
- 接口: 对实现接口的代码定义约束
-
理解使用TypeScript的好处,掌握TypeScript基础语法
- 编译时强类型
- 模块化: module
- 语法糖
- 容易上手
-
TypeScript的规则检测原理
-
可以在React、Vue等框架中使用TypeScript进行开发
React
-
React和vue选型和优缺点、核心架构的区别
-
React中setState的执行机制,如何有效的管理状态
-
React的事件底层实现机制
- 事件合成
- 对原生事件的封装和改造: SyntheticEvent
- 事件委派: 所有事件绑定在最外层, 统一事件监听和处理, 然后映射到具体的事件处理函数
- 自动绑定: 绑定this为当前组件
- 事件合成
-
React的虚拟DOM和Diff算法的内部实现
-
React的Fiber工作原理,解决了什么问题
- 构架
- Virtual DOM
- Reconciler: Diff运算
- Renderer: ReactDOM, ReactNative
- Fiber Reconciler: 优化Diff运算
- 阶段1: 生成fiber树; 这个过程可以被中断, 去执行优先级高的任务(键盘输入等)
- 阶段2: 批量更新; 不能打断
- 构架
-
React Router和Vue Router的底层实现原理、动态加载实现原理
- hash: onhashchange
- history
- onpopstate: 前进后退事件
- 全局监听a标签点击
- history.pushState钩子函数
- history.replaceState钩子函数
- 注册视图
- 路由改变时执行视图的回调函数
-
可熟练应用React API、生命周期等,可应用HOC、render props、Hooks等高阶用法解决问题
-
基于React的特性和原理,可以手动实现一个简单的React
Vue
-
熟练使用Vue的API、生命周期、钩子函数
-
MVVM框架设计理念
- view
- model
- viewmodel: 桥梁, 实现model变化时通知view更新
-
Vue双向绑定实现原理、Diff算法的内部实现
-
Vue的事件机制
-
从template转换成真实DOM的实现机制
多端开发
-
单页面应用(SPA)的原理和优缺点,掌握一种快速开发SPA的方案
- 优点
- 页面切换不需要重新加载整个页面
- 页面切换不会白屏
- 服务器压力小
- 缺点
- 首次加载耗时较长
- SEO问题
- css命名冲突
- 页面复杂度较高
- 优点
-
理解Viewport、em、rem的原理和用法,分辨率、px、ppi、dpi、dp的区别和实际应用
-
移动端页面适配解决方案、不同机型适配方案
-
掌握一种JavaScript移动客户端开发技术,如React Native:可以搭建React Native开发环境,熟练进行开发,可理解React Native的运作原理,不同端适配
-
掌握一种JavaScript PC客户端开发技术,如Electron:可搭建Electron开发环境,熟练进行开发,可理解Electron的运作原理
-
掌握一种小程序开发框架或原生小程序开发
-
理解多端框架的内部实现原理,至少了解一个多端框架的使用
数据流管理
-
掌握React和Vue传统的跨组件通信方案,对比采用数据流管理框架的异同
-
熟练使用Redux管理数据流,并理解其实现原理,中间件实现原理
-
熟练使用Mobx管理数据流,并理解其实现原理,相比Redux有什么优势
-
熟练使用Vuex管理数据流,并理解其实现原理
-
以上数据流方案的异同和优缺点,不情况下的技术选型
实用库
-
至少掌握一种UI组件框架,如antd design,理解其设计理念、底层实现
-
掌握一种图表绘制框架,如Echart,理解其设计理念、底层实现,可以自己实现图表
-
掌握一种GIS开发框架,如百度地图API
-
掌握一种可视化开发框架,如Three.js、D3
-
工具函数库,如lodash、underscore、moment等,理解使用的工具类或工具函数的具体实现原理
开发和调试
-
熟练使用各浏览器提供的调试工具
-
熟练使用一种代理工具实现请求代理、抓包,如charls
-
可以使用Android、IOS模拟器进行调试,并掌握一种真机调试方案
-
了解Vue、React等框架调试工具的使用
前端工程
项目构建
-
理解npm、yarn依赖包管理的原理,两者的区别
- yarn优点
- 速度快: 并行安装, 离线模式
- 安装版本统一
- yarn优点
-
可以使用npm运行自定义脚本
-
理解Babel、ESLint、webpack等工具在项目中承担的作用
-
ESLint规则检测原理,常用的ESLint配置
-
Babel的核心原理,可以自己编写一个Babel插件
-
可以配置一种前端代码兼容方案,如Polyfill
-
Webpack的编译原理、构建流程、热更新原理,chunk、bundle和module的区别和应用
- 热更新原理
- 当修改文件时
- 文件系统通知webpack
- webpack重新编译构建模块, 并通知HMR服务器需要更新
- HMR服务器使用websocket通知HMR运行时更新
- HMR运行时发起http请求新的模块
- HMR运行时替换新的模块, 如无法替换, 则刷新页面
- 热更新原理
-
可熟练配置已有的loaders和plugins解决问题,可以自己编写loaders和plugins
nginx
-
正向代理与反向代理的特点和实例
- 正向代理: 客户端代理
- 反向代理: 服务端代理
-
可手动搭建一个简单的nginx服务器
-
熟练应用常用的nginx内置变量,掌握常用的匹配规则写法
- 从请求行解析的变量: $request
- 从请求头解析的变量: $http_cookie
- 其他内置变量: $status
-
可以用nginx实现请求过滤、配置gzip、负载均衡等,并能解释其内部原理
# 负载均衡
upstream 192.168.3.41{
iphash; # ip的hash分配
least_conn; # 最少链接
server 192.168.3.42:80 weight=1;
server 192.168.3.43:80 weight=1;
}
server
{
listen 80;
server_name 192.168.3.41;
charset utf8;
client_max_body_size 50m;
client_body_buffer_size 256k;
# 配置gzip
gzip on;
gzip_buffers 32 4K;
gzip_comp_level 6;
gzip_min_length 100;
gzip_types application/javascript text/css text/xml;
gzip_disable "MSIE [1-6]\.";
gzip_vary on;
# 请求过滤
location ~ / {
if ( $query_string ~* ^(.*)?s=test/xxx/getAAInfo ){
return 555;
}
}
}
开发提速
-
熟练掌握一种接口管理、接口mock工具的使用,如yapi
-
掌握一种高效的日志埋点方案,可快速使用日志查询工具定位线上问题
- 手动埋点
- 声明式埋点
- 可视化埋点
- 自动埋点
-
理解TDD与BDD模式,至少会使用一种前端单元测试框架
- TDD: 测试驱动开发
- BDD: 行为驱动开发
- 测试框架:
- Karma
- Mocha
- jest
版本控制
-
理解Git的核心原理、工作流程、和SVN的区别
- 原理: 对象数据库,其中保存着git的对象
- blob: 文件内容
- tree: 对文件名、文件目录结构
- commit: 提交时间、版本作者、版本序列、版本说明
- 工作流
- 区别
- git是分布式
- 内容按元数据存储
- 分支不同
- 原理: 对象数据库,其中保存着git的对象
-
熟练使用常规的Git命令、git rebase、git stash等进阶命令
-
可以快速解决线上分支回滚、线上分支错误合并等复杂问题
持续集成
-
理解CI/CD技术的意义,至少熟练掌握一种CI/CD工具的使用,如Jenkins
-
可以独自完成架构设计、技术选型、环境搭建、全流程开发、部署上线等一套完整的开发流程(包括Web应用、移动客户端应用、PC客户端应用、小程序、H5等等)
项目和业务
后端技能
-
了解后端的开发方式,在应用程序中的作用,至少会使用一种后端语言
-
掌握数据最终在数据库中是如何落地存储的,能看懂表结构设计、表之间的关联,至少会使用一种数据库
性能优化
-
了解前端性能衡量指标、性能监控要点,掌握一种前端性能监控方案
-
了解常见的Web、App性能优化方案
-
SEO排名规则、SEO优化方案、前后端分离的SEO
-
SSR实现方案、优缺点、及其性能优化
-
Webpack的性能优化方案
-
Canvas性能优化方案
- 离屏渲染
- 分层画布
- 一次性绘制
- requestAnimationFrame执行动画
- 减少调用canvas的api
-
React、Vue等框架使用性能优化方案
- React
- Code Splitting
- shouldComponentUpdate避免重复渲染
- 使用不可突变数据结构
- 组件尽可能的进行拆分、解耦
- 列表类组件优化
- bind函数优化
- 不要滥用props
- ReactDOMServer进行服务端渲染组件
- React
前端安全
-
XSS攻击的原理、分类、具体案例,前端如何防御
-
CSRF攻击的原理、具体案例,前端如何防御
-
HTTP劫持、页面劫持的原理、防御措施
业务相关
-
能理解所开发项目的整体业务形态、业务目标、业务架构,可以快速定位线上业务问题
-
能理解所开发项目整体的技术架构、能快读的根据新需求进行开发规划、能快速根据业务报警、线上日志等定位并解决线上技术问题
-
可以将自己的想法或新技术在业务中落地实践,尽量在团队中拥有一定的不可替代性