网络优化
- dns寻址过程
第一阶段:本地主机
1.host文件是否存在网址映射
2.本地dns解析器是否存在网址映射
第二阶段:本地服务器
1.本地配置区域资源是否存在网址映射
2.服务器缓存是否映射
第三阶段:网络服务器
1.是否采用转发模式
- tcp的三次握手和四次挥手,以及为何要三次和为何要四次
三次握手:
TCP是通过程序实现的,可靠的,面向连接的协议。而程序是严谨的,每一次建立连接都会进行“三次握手”这样的步骤。建立连接的目的是为了可靠的数据传输。
四次挥手:
三次握手是为了建立可靠的数据传输通道,四次挥手是为了保证等数据传输完再关闭连接,保证双方都达到关闭连接的条件才能断开。
疑问:
服务端的SYN和ACK报文可以一起发送,但是挥手时有数据传输,ACK和FIN报文不能同时发送,需要分为两步,所以多了一步流程。
- http1.0,http1.1以及http2.0的区别?
http1.0:
每次请求都需要重新建立tcp连接,请求完后立即断开与服务器连接,这很大程度造成了性能上的缺陷,http1.0被抱怨最多的就是连接无法复用。
http1.1:
引入了长连接(keep-alive),相较于1.0减少了连接和关闭的延迟,提高了效率,但是若干个请求还是需要串行排队处理,如果一旦某个请求超时,后面的就会被阻塞,也就是常说的线头阻塞。
http2:
1.新的二进制格式传输:二进制即0和1的组合,实现方便健壮,而1.x版本是基于文本,解析存在缺陷
2.多路复用:一个连接可以有多个请求,且可以混杂在一起根据requestid来区分不同的请求,提高了连接的利用率,降低了延迟
3.header头部压缩:通讯两方各自缓存了一份 header请求头表,避免了重复的header传输,且缩小了包的体积大小
4.服务端推送功能:可以服务端主动向客户端push消息
- cdn的原理、cdn的适用场景?
原理:
CDN(内容分发网络)是将源站内容分发至最接近用户的节点,使用户可就近取得所需内容,提高用户访问的响应速度和成功率。解决因分布、带宽、服务器性能带来的访问延迟问题,适用于站点加速、点播、直播等场景。
场景:
1、网站站点/应用加速
2、视音频点播/大文件下载分发加速
3、视频直播加速
4、移动应用加速移动
核心点:
1、缓存:就是说我们把资源 copy 一份到 CDN 服务器上这个过程
2、回源就是说 CDN 发现自己没有这个资源(一般是缓存的数据过期了),转头向根服务器(或者它的上层服务器)去要这个资源的过程。
- 浏览器缓存有哪几种,它们的区别是什么?
浏览器缓存:强缓存和协商缓存
区别:
强缓存:
1. 不会向服务器发送请求,直接从本地缓存中获取数据
2. 请求资源的的状态码为: 200 ok(from memory cache)
协商缓存:
1. 向服务器发送请求,服务器会根据请求头的资源判断是否命中协商缓存
2. 如果命中,则返回304状态码通知浏览器从缓存中读取资源
总结:
强制缓存优先于协商缓存进行,若强制缓存(Expires和Cache-Control)生效则直接使用缓存,若不生效则进行协商缓存(Last-Modified / If-Modified-Since和Etag / If-None-Match),协商缓存由服务器决定是否使用缓存,若协商缓存失效,那么代表该请求的缓存失效,重新获取请求结果,再存入浏览器缓存中;生效则返回304
- 解释一下websocket的作用?
作用:建立服务器和客户端的长连接能更好的节省服务器资源和带宽,服务器向浏览器推流实现实时通信。
WebSocket方法:
- Socket.send():向服务器发送数据
- Socket.close():关闭连接
WebSocket事件:
- Socket.onopen:连接建立时触发
- Socke.onmessage:客户端接受服务端数据时触发
- Socket.onerror:通信错误时触发
- Socket.onclose:连接关闭时触发
渲染优化
- webpack如何提高构建速度?
1.多入口情况下,使用CommonsChunkPlugin来提取公共代码
2.通过externals配置来提取常用库
3.利用DllPlugin和DllReferencePlugin[预编译]资源模块 通过DllPlugin来对那些我们引用但是绝对不会修改的npm包来进行预编译,再通过DllReferencePlugin将预编译的模块加载进来。
4.使用Happypack 实现[多线程]加速编译
5.使用webpack-uglify-parallel来提升uglifyPlugin的压缩速度。 原理上webpack-uglify-parallel采用了多核并行压缩来提升压缩速度
6.使用Tree-shaking和Scope Hoisting来剔除多余代码
- bfc是什么?bfc有什么特性?如何生成?
是什么:
是块级格式化上下文。独立的渲染区域。
有什么特性:
- BFC是一个块级元素,块级元素在垂直方向上依次排列。
- BFC是一个独立的容器,内部元素不会影响容器外部的元素。
- 属于同一个BFC的两个盒子,外边距margin会发生重叠,并且取最大外边距。
如何形成:
- display:flex或display:inline-block
- position:fixed或position: absolute
- overflow: hidden
什么是重绘和回流?
重绘:
当页面中元素样式的改变并不影响它在文档流中的位置时,也就是说布局没有发生改变时(比如只是改变元素的颜色)。
回流:
当渲染树(Render Tree)中的部分(或全部)元素的尺寸、结构、显示隐藏等发生改变时,浏览器重新渲染的过程称为回流
注意:
- 回流必定会发生重绘,重绘不一定会引发回流。
- 回流比重绘的代价要更高。有时即使仅仅回流一个单一的元素,它的父元素以及任何跟它相关的元素也会产生回流,牵一发动全身。
- 影响回流的因素?
(1)添加或者删除可见的 DOM 元素(不可见元素不会触发回流);
(2)元素尺寸或位置发生改变
(3)元素内容变化,比如文字数量或图片大小
(4)浏览器窗口大小发生改变
(5)CSS伪类的激活(例如::hover,从而改变了元素的布局的)
- 如何减少重绘和回流?
CSS
- 使用transform代替top;
- 使用visibility代替display:none,前者引起重绘,后者引发回流;
- 避免使用table布局;
- 尽可能在DOM树最末端改变class;
- 避免设置多层内联样式,css选择符从右往左匹配查找,避免节点层级过多;
- 将动画效果应用到position属性为absolute或fixed的元素上,避免影响其他元素的布局;
- 避免使用css表达式,可能会引发回流;
- css硬件加速;
JavaScript
- 避免频繁操作样式,修改class最好;
- 避免频繁操作DOM,合并多次修改为一次;
- 避免频繁读取会引发回流/重绘的属性,将结果缓存;
- 对具有复杂动画的元素使用绝对定位,使他脱离文档流。
- 场景:如何优化首屏
- 首屏请求和非首屏请求拆分
- 图片都应该使用懒加载的形式加载
- 使用preload预加载技术,以及prefetch的dns预解析
- 与首屏无关的代码可以加async甚至是defer等待网页加载完成后运行
- 虚拟长列表渲染
- 图片懒加载
- 使用事件委托
- 使用SSR
js基础
- let,const ,var 的区别
- var属于函数作用域能重复赋值和声明,会成变量提升
- const属于块级作用域只能声明一次且值不能被修改,会形成暂时性死区
- let属于块级作用域不能重复声明,能重复赋值,会形成暂时性死区
- new的执行过程
- new会创建一个新的空对象
- new会让this指向新对象
- 执行构造函数,给这个新对象添加属性和方法
- new会返回这个新对象
- 箭头函数中this和function里的this有什么区别
- 全局this指向window,普通this指向被调用的对象,箭头函数的this指向父级函数
- 普通this能被call()、apply()、bind()改变this指向,箭头函数的this不可以被改变
- 箭头函数中的this没有原型属性,不能使用构造函数,不能使用new
- call、bind、apply的区别
- call传参的是参数列表,会立即执行
- apply传参是数组对象,会立即执行
- bind传参是参数列表,不会立即执行,会生成一个新的函数
- 原型链和原型是什么?,
原型:每个函数都包含不同的原型对象,当将函数用做构造函数的时候,新的函数对象对继承原函数实例对象的属性和方法
原型链:当访问一个对象的属性或方法时没有找到,那么就会去原型上查找,如果找不到会继续在这个原型对象上继续查找,直到指向null
- 什么是事件循环机制?
事件循环机制执行过程主要分为同步任务和异步任务,
同步任务会直接执行进入主线程,异步任务会进入事件队列。
当执行到宏任务时遇到微任务,会将微任务推动队列中执行,
如果下一次执行还有微任务则继续执行,直到剩下的微任务执行完再执行宏任务!
- commonjs和AMD,CMD的区别,以及跟ES6 MODULE的区别
1. AMD/CMD/CommonJs 是js模块化开发的规范,对应的实现是require.js/sea.js/Node.js
2. CommonJs 主要针对服务端,AMD/CMD/ES Module主要针对浏览器端(服务端一般采用同步加载的方式,浏览器端需要异步加载)
3. AMD/CMD区别,虽然都是并行加载js文件,但还是有所区别,AMD是预加载,在并行加载js文件同时,还会解析执行该模块(因为还需要执行,所以在加载某个模块前,这个模块的依赖模块需要先加载完成);而CMD是懒加载,虽然会一开始就并行加载js文件,但是不会执行,而是在需要的时候才执行。
4. CommonJs和ES6 Module的区别:
- CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
- CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。
- CommonJS 模块的require()是同步加载模块,ES6 模块的import命令是异步加载,有一个独立的模块依赖的解析阶段。
- 说说require.cache
`webpack`是基于`nodejs`开发的一个文件打包工具,
在其5.X版本的文档中讲到模块缓存多处引用同一模块,
最终只会产生一次模块执行和一次导出。
所以,会在运行时(runtime)中会保存一份缓存。删除此缓存,则会产生新的模块执行和新的导出。
- 常用的ts中的数据类型?
- boolean(布尔类型)
- number(数字类型)
- string(字符串类型)
- array(数组类型)
- tuple(元组类型)
- enum(枚举类型)
- any(任意类型)
- null 和 undefined 类型
- void 类型
- never 类型
- object 对象类型
- es6中Map以及Set的区别是什么
- Map是一种字典的数据结构。set是一种集合的数据结构
- Map主要用于数据存储,set主要用于数组去重
- 常见js的类型转换
- Number()
- parseInt()
- String()
- Boolean()
- 如何捕获异步的异常,你能说出几种方案
- try-catch
- Promise.reject
- async await
- 作用域是什么,作用域链呢?
作用域分为全局作用域、函数作用域、块级作用域
作用域链:每个函数都有自己的作用域链,当查找自己的变化或者方法时,需要从局部向全局去查找。这个过程为作用域链。
css基础
- position有哪几种属性,它们的区别是什么
fixed相对于浏览器窗口定位,不会随着滚动条滚动
absolute相对于父元素进行定位,脱离标准流
relative基于自身定位,没有脱离标准流,占据空间
static没有定位,是默认值
- 怪异盒模型和一般盒模型有什么区别
标准盒模型由四部分组成,改变border、padding会改变盒子大小
怪异盒模型由两部分组成,改变border、padding不会改变盒子大小
- flex:1代表什么,flex-shrink和flex-grow有什么区别
flex:1代表flex-grow:1,flex-shrink:1,flex-basic:0;
flex-shrink和flex-grow分别代表子元素缩小和放大,flex-basic代表基础的宽度
- 移动端高清屏图片的解决方案
方案一 百分比布局
方案二 媒体查询调整
方案三 flex布局
方案四 使用rem单位
- 高清屏1px边框问题的解决方案?
- 伪类+transform(scale) 实现
- border-image, backgroud-image 实现
- viewport+rem
- 说说GPU加速
利用transform: translateZ(0),欺骗浏览器开启GPU加速
优点:
利用了GPU合成图层实现动画,可以做到动画平滑、流畅动画合成工作在GPU线程,不会被CPU的js运行阻塞
缺点:
绘图层必须传输到GPU,当图层较多时传输过程可能会导致渲染缓慢 每个复合层都需要消耗额外的内存,过多的内存可能导致浏览器的崩溃
微信小程序
- 数据请求怎么封装
- 将所有的接口放在统一的 js 文件中并导出(或者将请求地址、头、方法在一个 js 文件里统一定 义为一个常量并导出)
- 在 app.js 创建封装请求数据的方法
- 在子页面中调用封装的方法请求数据
- 参数传值的方法
给 HTML 元素中添加 data-*属性来传递需要的值,
之后通过 e.currentTarget.dataset 或 onload 的 param 参数获取。
注意不能有大写字母,不可以存放对象 跳转页面时通过 navigator 传递需要的参数值
设置 id 的方法标识,通过 e.currentTarget.id 获取设置的 id 值,然后通过设置全局变量的方法来传 递数值
- 提高小程序的应用速度的方法
- 减少默认 data 的大小
- 组件化方案,公用的如弹框等写个自定义的组件,然后调用
- 小程序的优点
- 无需下载
- 打开速度快
- 开发成本低
- 为用户提供良好的安全保障。发布有一套严格的审查流程,不能通过审查的程序无法发布上线
- 服务请求快
- 小程序的缺点
- 依托微信,不能开发后台管理功能
- 大小限制不能超过 2M,不能打开超过 5 个层级的页面
- 简述小程序原理
- 小程序分为两个部分 webview 和 appService,webview 用来展现 UI,appService 用来处理业
务逻辑、数据及接口调用,它们在两个进程中运行,通过系统层 JSBridge 实现通信,完成 UI 渲 染、事件处理。
- 小程序和 Vue 写法的区别
- 循环遍历:小程序是 wx:for=“list”,vue 是 v-for=“inforin list”
- 调用 data 模型:小程序是 this.data.unifo,vue 是 this.unifo
- 给模型赋值:小程序是 this.setData({unifo:1}),vue 是直接 this.unifo=1
- 小程序的双向绑定和 vue 哪里不一样
- 小程序直接 this.data 的属性是不可以同步到视图的,必须调用 *this.setData({})*
- 1px = 2rpx
- 生命周期函数
- onLoad——页面加载,调一次
- onShow——页面显示,每次打开页面都调用
- onReady——初次渲染完成,调一次
- onHide——页面隐藏,当 navigateTo 或底部 tab 切换时调用
onUnload——页面卸载,当 redirectTo 或navigateBack 时调用
- 几种跳转,小程序内的页面跳转
- wx.navigateTo——保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面(参数必 须为字符串)
- wx.redirectTo——关闭当前页面,跳转到应用内的某个页面。但是不允许跳转到 tabbar 页面
- wx.switchTab——跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面,路径后不能带参数
- wx.navigateBack——关闭当前页面,返回上一页面或多级页面。可通过 getCurrentPages() 获取
当前的页面栈,决定需要返回几层
- wx.reLaunch——关闭所有页面,打开到应用内的某个页面 通过 navigator 跳转
- 如何自定义组件
- 先创建一个 components 文件夹,用来存放所有自定义组件的,目录结构依然是 js,wxml,json,wxss
- 基本配置: .json——进行自定义组件声明 { “component”: true }
- 使用组件: 假如在 index.wxml 中使用这个自定义的组件,首先在 index.json 中进行声明 {
“usingComponents”: { “toastdemo”: “/components/toastdemo/toastdemo” }
}
- 接着在 index.wxml 中引用
- 然后在 index.js 进行配置
- 使用时直接执行 this.toastdemo.showToast(‘弹框组件调用成功’,2000)就可以了
- 如何实现下拉刷新
先在 app.json 或 page.json 中配置 enablePullDownRefresh:true page 里用 onPullDownRefresh 函数,在下拉刷新时执行 在下拉函数执行时发起数据请求,请求返回后,调用 wx.stopPullDownRefresh 停止下拉刷新的状态
- bindtap 和 catchtap 的区别是什么
bindtap 不会阻止冒泡事件,catchtap 阻止冒泡
- setData 的回调函数
微信小程序的 setData 实现是和 react 的 setData 实现类似的,所以它也是一个异步函数,并且有 回 调函数的参数,当然平时小量数据我们可能并没有感觉到它的异步,但是为了确保逻辑的正确执行,在需要 用到 setData 后 data 里的数据的步骤,请写入 setData 的回调函数中,如下示例:
this.setData({ a: this.data.a++ },()=>{ })
- 分包的操作,发布的时候是选择某个包来发吗
- 分包:主包添加跳转路径,分包放内容,在 app.json 配置 subpakeages 声明项目分包结构。代码 包总包大小为
12M,单个主包/分包大小不能超过 2M。
- 按照功能划分的打包原则:可以按照功能的划分,拆分成几个分包,当需要用到某个功能时,才加载 这个功能对应的分包;公共逻辑、组件放在主包内。
- 首次启动时,先下载小程序主包,显示主包内的页面;如果进入了某个分包的页面,再下载这个对应分 包,下载完毕后,显示分包的页面,
- 总结:首先配置好打包路径,tabbar 页面必须在主包内。各分包之间不能互相调用,能调用主包内 的分包加载,预分包加载
- 小程序页面间有哪些传递数据的方法
- 使用全局变量实现数据传递:在 app.js 文件中定义全局变量 globalData将需要存储的信息存放在里面: // app.js
App({ // 全局变量 globalData: { userInfo: null } })
- 使用的时候,直接使用 getApp()拿到存储的信息
- 使用 wx.navigateTo 和 wx.redirectTo 的时候,可以将部分数据放在 url 里,并在新页面 onLoad 的
时候初始化
跨端uniapp
- 简述uniapp实现原理
逻辑层和视图层分离,非H5端通信有折损
uni-app 在非H5端运行时,从架构上分为逻辑层和视图层两个部分。逻辑层负责储存数据和执行业务逻辑,视图层负责页面渲染。
页面加载时,联网和逻辑运算在逻辑层(Android是v8,iOS是jscore),然后会传递数据给视图层渲染。这种通信有损耗。同样,在视图层操作时,比如拖动页面,要实时传递事件给逻辑层接收,也是有损耗的。
- uni-app的优点
跨平台发行,运行体验更好
- 与小程序的组件、API一致;
- 兼容weex原生渲染,增加了开发效率高,但是由于weex坑比较多,建议还是使用局部渲染优化;
通用前端技术栈,学习成本更低
支持vue语法,微信小程序API
- 内嵌mpvue
- 开发生态,组件更丰富
支持通过npm安装第三方包
- 支持微信小程序自定义组件及JS SDK
- 兼容mpvue组件及项目(内嵌mpvue开源框架)
- App端支持和原生混合编码
- 插件丰富,DCloud将发布插件到市场
安全
- csrf是什么,防范措施是什么
是什么:
跨站请求伪造,是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。
防范措施:
1.验证 HTTP Referer 字段
2、验证码
3、添加token验证
- xss是什么?如何防范?
是什么:
XSS攻击(跨站点脚本攻击),意即黑客恶意篡改你网页的前端代码,在里面注入一些恶意的 html+javascript的脚本,在你的浏览器内运行,获取你的信息,进行一些恶意操作。
(1)输入过滤
(2)输出转义
(3)使用 HttpOnly Cookie
浏览器相关
- 跨域是如何产生的,如何解决
原因:
跨域是由于浏览器存在同源策略,两个页面之间,如果协议、主机和端口中有任意一个不同,就会出现跨域问题
如何解决:
1. JSONP
1. Nginx代理
1. 后台设置
1. vue前端代理
- 如何检查性能瓶颈
1. 比如大列表的渲染,大量dom的渲染;
1. 大量图片的加载,过多资源的请求,资源体积是否过大,;
1. 代码中有没有耗时的计算操作,或则大量循环.递归
1. 编写的组件过于庞大 层级过深,依赖模块过多等.
- 打开页面白屏,如何定位问题,或者打开页面CPU100%,如何定位问题
1、先确保网络连接通畅。
2、查看网络url地址是否输入有误。
3、打开控制台查看报错信息。
4、查看接口访问是否有请求。
5、查看路由是否有path或者name的错误,导致加载了不存在的页面。
- jsonp的原理?
Jsonp原理:利用script标签没有跨域限制,
通过src属性发送带有callback参数的get请求。
服务器将参数传入到callback函数返回给浏览器解析,从而在前端运行,缺点是只能发送get请求
框架相关
- react和vue的区别
- key的作用是什么,为何说要使用唯一key,vue的diff算法是如何实现的,vue的呢
- 听过闭包陷阱么,为何会出现这种现象,如何避免
- vue的响应式原理
- 为何vue3.x用的是proxy而不是object.defineProperties
- vue是如何实现对数据的监听的,对数组呢
- Vue 生命周期 以及其父子组件的生命周期调度顺序
weboack相关
- webpack有哪些常见 loader 和 plugin,你用过哪些?
loader:
file-loader:把文件输出到一个文件夹中,在代码中通过相对 URL 去引用输出的文件
source-map-loader:加载额外的 Source Map 文件,以方便断点调试
image-loader:加载并且压缩图片文件
babel-loader:把 ES6 转换成 ES5
css-loader:加载 CSS,支持模块化、压缩、文件导入等特性
eslint-loader:通过 ESLint 检查 JavaScript 代码
plugin:
define-plugin:定义环境变量
commons-chunk-plugin:提取公共代码
uglifyjs-webpack-plugin:通过UglifyES压缩ES6代码
算法实现(待更新)
- js大整数加法
- 双指针
- 经典排序
- 动态规划
- 贪心算法
- 回溯法
- DFS
- BFS
- 链表操作
- 线性求值
项目相关(待更新)
- 项目中遇到的最大问题是什么,如何解决的
- nodejs作为中间层的作用是什么
场景题(待更新)
- 如何实现直播上的弹幕组件,要求不能重叠,仿照b站上的弹幕
- 如何实现动态表单,仿照antd上的form组件
- 实现一个promise(一般不会这样问)
- 实现一个限制请求数量的方法
- 如何实现一个大文件的上传
- 实现一个eventEmitter
- 实现一个new,call,bind,apply
- 实现一个throttle,debound
- 实现promise.then,finally,all
- 实现继承,寄生组合继承,instanceof
- 实现Generator,Aynsc