OSI七层模型
应用层,对APP数据进行编码,展示给用户的图片,声音,视频,http协议,
表示层,编码和解码
会话层,两个APP之间的会话,
传输层,建立TCP和UDP的连接,TCP要求整个文件完整,但是会造成延时,UDP实时采集,但是会丢帧。
网络层,基于IP地址进行路由转发,寻址,路由选择,帧变成包,
数据链路层,各段链路的通信协议,数据传输过程中有不同的协议,数据传输过程中,封装成帧,
物理层,实际传输,物理传输
TCP/IP模型
应用层,会话层,传输层,网络层,数据链路层
TCP和UDP
基于连接的是tcp,三次握手,客户先初始确认连接发包,服务接收返回确认信息,客户提出请求,传输确认,四次挥手,非连接的是udp
TCP三次握手
客户端发出连接请求,服务端收到,客户端提出请求,
HTTP请求码
1表示请求,2表示请求成功,200请求成功,201创建成功,可以进行post和pull了,204返回的无内容,3表示重定向,301表示资源更新,url更新
302临时url,304未修改,可以直接用缓存,400语法错误,401身份未识别,403拒接普通请求,404没有资源,409冲突,500服务器出错,502网关错误,503超载维护。
webpack原理
首先入口文件,根据逐层识别模块依赖,commonjs和es6的import进行分析,然后分析代码,转化代码,编译代码,输出代码,最终打包
loader加载
文件加载器,资源文件,进行编译压缩,统一打包到指定文件,处理一个文件可以多个loader,loader执行顺序和配置顺序相反,最后一个loader先执行,执行函数把文件内容作为参数,然后执行之后的返回值作为下一个loader的参数,最后执行的loader返回js源码。
plugin生成
监听webpack生命周期期间广播的事件,合适的时候对webpack提供的api改变输出结果
区别
loader直接编译操作文件,plugin基于事件工作,监听打包过程的节点,并执行相应任务
防抖节流
防抖就是推迟执行触发函数,当一直触发函数时,函数会一直重置推迟事件,跟LOL里的回城一样。
频繁点击事件,监听浏览器滚动事件,监听用户缩放事件
// 第一个参数是需要进行防抖处理的函数,第二个参数是延迟时间,默认为1秒钟
function debounce(fn, delay = 1000) {
// 实现防抖函数的核心是使用setTimeout
// time变量用于保存setTimeout返回的Id
let time = null
function _debounce() {
// 如果time不为0,也就是说有定时器存在,将该定时器清除
if (time !== null) {
clearTimeout(time)
}
time = setTimeout(() => {
fn()
}, delay)
}
// 防抖函数会返回另一个函数,该函数才是真正被调用的函数
return _debounce
}
这样只是实现了简单防抖,下面介绍传入参数的情况,
由于外部接收的事件,都在fn里面,所以我们需要在防抖函数调用fn的时候apply(this,arguments)这样把参数传输进去
但是我们第一次也会延迟,为了解决这个问题,我们需要
在debounce再传入一个Boolean参数,如果为true,设置一个变量firstClick记录值为!time,然后判断firstClick为真,就直接执行,然后给time设置一个计时函数,把t变回null,如果参数不为true就直接执行计时函数。
节流就是技能CD,触发时会立即执行,但是需要冷却时间
// interval 间隔时间,也就是cd的长短
function throttle(fn, interval) {
//该变量用于记录上一次函数的执行事件
let lastTime = 0
const _throttle = function(...args) {
// 获取当前时间
const nowTime = new Date().getTime()
// cd剩余时间
const remainTime = nowTime - lastTime
// 如果剩余时间大于间隔时间,也就是说可以再次执行函数
if (remainTime - interval >= 0) {
fn.apply(this, args)
// 将上一次函数执行的时间设置为nowTime,这样下次才能重新进入cd
lastTime = nowTime
}
}
// 返回_throttle函数
return _throttle
}
ajax怎么使用promise封装
说说promise 说说 async await
vue响应式原理
vue
将data
初始化为一个Observer
并对对象中的每个值,重写了其中的get
、set
,data
中的每个key
,都有一个独立的依赖收集器。在get
中,向依赖收集器添加了监听在mount时,实例了一个Watcher
,将收集器的目标指向了当前Watcher
在data
值发生变更时,触发set
,触发了依赖收集器中的所有监听的更新,来触发Watcher.update
传统项目与框架区别 两者优势
码层面的问题
原生JS 框架
1.缺少规划,代码混乱 ----> 结构化开发
//原生js的代码写的很随意,没有规划性
2.缺少限制,容易冲突 ----> 独立文件,独立作用域
//原生js开发不是多人并行开发,修改代码容易造成全局变量和其他业务发生变化
//框架借助glub和webpack等工程化工具,实现各页面独立开发,相互不影响,有自己的作用域,只要本作用 域的变量不发生冲突,与其他页面的变量问题就不会产生冲突,最重要的是解决了多人并行开发的问题
3.缺少支撑,能力要求高 ----> 提供支持,只关心业务
//原生JS要负责前端的架构、工具、业务等;而框架的架构和工具都做了集成,只关心业务逻辑即可
效率问题
原生JS 框架
1.关注所有流程 -----------> 只关注业务
//原生js开发者要关注业务外的所有流程,还不能并行开发,浪费很多时间,效率低下
//框架的出现使得开发者只需要关注前端的业务逻辑实现,不需要关注其他,提高了效率
2.团队效率低 ------------> 并行开发
//js一个人开发改动会影响其他人的代码和功能实现,只能等一个人开发完了其他开发者才能继续开发
//框架开发只要接口和参数不变,只会影响自己的模块,对别人的模块不会产生影响,可以多人并行开发
3.测试效率低 ------------> 模块测试,自动化测试
//js的影响是全局的,一个业务改动会覆盖全局,测试也是要再次进行全局测试
//模块改动只会影响本模块和有业务关系的模块,测试范围缩小;还有的支持工具测试和自动化测试,极大 地提高了测试的效率
多页应用的问题
原生JS 框架
1.路由体验问题 ---------> 使用单页路由
//原生js会加载所有内容,导致所有html,css,js,请求都要重新加载,耗费时间长
//框架的html,css,js都是提前加载好的只用请求数据,页面显示很快
2.无页面切换效果 ---------> 可以添加过场动画
//原生js切换页面,整个页面会销毁,加载会出现白屏,用户体验不高
//框架是单页,加载并不会整个页面销毁,页面切换实际就是好DOM元素的切换,可以添加过场动画提高视 觉效果
3.浪费服务器资源 --------> 减少服务器请求
//原生js加载会销毁整个页面,重新请求资源加载,加重服务器负担
//框架只请求数据,大大减少了服务器负担
框架开发的不足(缺点)
兼容性问题,SEO不友好(对低版本浏览器,向ES6这样的不友好)
有场景要求,开发自由度比较低
黑盒开发,框架本身有出错的风险(使用的API接口,内部实现是不可见的)
学习成本(学习设计思路和API的用法)
为什么可以通过 this.xxx 触发响应式流程
项目中什么用的 vuex
状态管理,大型单页项目用到同一个状态,所以需要vuex进行状态管理,vue组件调用actions,actions提交到mutations,mutations再把变化传递给state,然后渲染到组件上
重排重绘
渲染里面生成布局就是重排,布局绘画就是重绘,dom变化影响了元素的几何信息,浏览器需要计算,安置,这就是重排,回流
添加删除dom,改变元素位置,尺寸,内容,字体大小,窗口尺寸,激活伪类,设置style,
不影响布局只是单单影响元素外观进行绘制,就是重绘,
js 闭包 细节题:如果父函数有a,b变量 子函数引用b变量 退出父函数 a变量会被销毁吗
js对象的继承
组合继承,父类.call(this,value) 子类.prototype=new 父类 寄生组合继承,用object.create,第二个参数是构造器。
class继承,用extends,构造器用super
统计字符串中字符出现的次数,返回出现频率最高的次数以及出现这些次数的字符
适配移动端怎么做的 什么样的效果
使用flexible调整fonsize的依据
哪些场景适合用rem、哪些适合px
多端设备,适合rem
position
flex 怎么用的 说说下面三个子元素占据宽度是多少
跨域
bind,call,apply
登陆持久化
用户信息为啥放在localStorage
伪造域名窃取本地token怎么办
使用路由守卫进行权限管理
js基本数据类型,==和===,事件循环理解,深浅拷贝,闭包理解和举例,vue和react声明周期,正则表达式,日期格式化,
number string boolean null undefied symbol 转化判断,直接判断,_.clone(obj) _.clonedeep(obj)
object.assign(obj) {…obj} JSON.parse(JSON.stringify(obj))
tcp队首阻塞,七层网络模型,进程和线程,小程序和web渲染区别,axios拦截,统计请求时长,electron底层线程,js的worker,css新标准,vuerouter模式原理,vue2和3区别,顺时针打印矩阵,解析url参数,
tcp和udp区别,图片懒加载,http状态码,缓存,数组扁平,小于n最大数,sleep函数,域名共享cookie,
前后端认证方式,webpack版本区别,plugin和loader,hooks优点,
flex布局
https://blog.csdn.net/xiaomao_wxj/article/details/107747964
移动端适配
https://juejin.cn/post/6953091677838344199
es6
https://juejin.cn/post/7091066836061519908
grunt,gulp自动化
https://juejin.cn/post/6850418112026984462
webpack
https://juejin.cn/post/6943468761575849992#heading-7
TCP和UDP
https://juejin.cn/post/6844903800336023560
进程和线程
https://juejin.cn/post/7146410097281859591
vue生命周期
https://juejin.cn/post/7032881219524100132
call apply bind
https://juejin.cn/post/6844903891092389901
手写promise
http://jingqun.top/webwork/6-%E6%89%8B%E5%86%99%20Promise.htm
const PENDING = ‘pending’
const RESOLVED = ‘resolved'
const REJECTED = 'rejected'
function MyPromise(fn){
把this给that
设置state为pending
设置value为null
设置resolvedCallbacks为空数组
设置rejectedCallbacks为空数组
其中value保存reject和resolve传入的值,剩下俩数组用于保存then后的回调,当promise执行完后可能状态还是等待
完善resolve函数
function resolve(value){
判断state是不是pending
如果是设置state为resolved
value为value
resolvedCallbacks数组map(cb = >cb(that.value))}
reject同理
接下来实现如何执行Promise传入的函数
try{
fn(resolve,reject)}
catch(e){reject(e)}
实现复杂的then函数
MyPromise.prototype.then=function(onFulfilled,onRejected){
把this给that
onFulfilled=typeof onFulfilled==='function'?onFulfilled :v=>v
onRejected = typeof onRejected === 'function' onRejected :r=>{throw r}
如果状态是pending
两个数组同时push
如果是rejectd执行onRejected(this.value)
如果是resolved同理