转自:https://zhuanlan.zhihu.com/p/534307734
补充:https://blog.csdn.net/m0_65450343/article/details/124658549
https://blog.csdn.net/xiaozgm/article/details/125770888
https://zhuanlan.zhihu.com/p/471197797
浏览器
输入一个URL到页面过程中发生了什么(高频)
- 首先在浏览器中输入URL
- 查找缓存:浏览器先查看浏览器缓存-系统缓存-路由缓存中是否有该地址页面,如果有则显示页面内容。如果没有则进行下一步。
- DNS域名解析:浏览器向DNS服务器发起请求,解析该URL中的域名对应的IP地址。DNS服务器是基于UDP的,因此会用到UDP协议。
- 建立TCP连接:解析出IP地址后,根据IP地址和默认80端口,和服务器建立TCP连接
- 发起HTTP请求:浏览器发起读取文件的HTTP请求,,该请求报文作为TCP三次握手的第三次数据发送给服务器
- 服务器响应请求并返回结果:服务器对浏览器请求做出响应,并把对应的html文件发送给浏览器
- 关闭TCP连接:通过四次挥手释放TCP连接
- 浏览器渲染:客户端(浏览器)解析HTML内容并渲染出来,浏览器接收到数据包后的解析流程为:
- 构建DOM树:词法分析然后解析成DOM树(dom tree),是由dom元素及属性节点组成,树的根是document对象
- 构建CSS规则树:生成CSS规则树(CSS Rule Tree)
- 构建render树:Web浏览器将DOM和CSSOM结合,并构建出渲染树(render tree)
- 布局(Layout):计算出每个节点在屏幕中的位置
- 绘制(Painting):即遍历render树,并使用UI后端层绘制每个节点。
浏览器渲染机制、重绘、重排
网页生成的过程:
- 构建DOM树:词法分析然后解析成DOM树(dom tree),是由dom元素及属性节点组成,树的根是document对象
- 构建CSS规则树:生成CSS规则树(CSS Rule Tree)
- 构建render树:Web浏览器将DOM和CSSOM结合,并构建出渲染树(render tree)
- 布局(Layout):计算出每个节点在屏幕中的位置
- 绘制(Painting):即遍历render树,并使用UI后端层绘制每个节点。
重排:当DOM的变化影响了元素的几何信息(DOM对象的位置和尺寸大小),浏览器需要重新计算元素的几何属性,将其安放在界面中的正确位置,这个过程叫做重排。
触发条件:
- 添加或者删除可见的DOM元素
- 元素尺寸改变——边距、填充、边框、宽度和高度
重绘:当一个元素的外观发生改变,但没有改变布局,重新把元素外观绘制出来的过程,叫做重绘。
触发条件:改变元素的color、background、box-shadow等属性。
HTML
常见的语义化标签
header nav main article section aside footer
语义化的优点如下:
- 对机器友好,带有语义的文字表现力丰富,更适合搜索引擎的爬虫爬取有效信息,有利于SEO。除此之外,语义类还支持读屏软件,根据文章可以自动生成目录;
- 对开发者友好,使用语义类标签增强了可读性,结构更加清晰,开发者能清晰的看出网页的结构,便于团队的开发与维护。
H5 新特性
- 语义化标签
- 媒体标签
- 表单
- DOM查询操作
- Web存储
- 拖拽
script标签中defer和async的区别
多个带async属性的标签,不能保证加载的顺序;多个带defer属性的标签,按照加载顺序执行;
async属性,表示后续文档的加载和执行与js脚本的加载和执行是并行进行的,即异步执行;defer属性,加载后续文档的过程和js脚本的加载(此时仅加载不执行)是并行进行的(异步),js脚本需要等到文档所有元素解析完成之后才执行,DOMContentLoaded事件触发执行之前。
CSS
盒模型(高频)
盒模型都是由四个部分组成的,分别是margin、border、padding和content。
- 标准盒模型的width和height属性的范围只包含了content,
- IE盒模型的width和height属性的范围包含了border、padding和content。
flex常用属性(高频)
- flex-direction属性决定主轴的方向(即项目的排列方向)。
- flex-wrap属性定义,如果一条轴线排不下,如何换行。
- flex-flow属性是flex-direction属性和flex-wrap属性的简写形式,默认值为row nowrap。
- justify-content属性定义了项目在主轴上的对齐方式。
- align-items属性定义项目在交叉轴上如何对齐。
- align-content属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。
position属性
- 固定定位 fixed: 元素的位置相对于浏览器窗口是固定位置,即使窗口是滚动的它也不会移动。Fixed 定 位使元素的位置与文档流无关,因此不占据空间。 Fixed 定位的元素和其他元素重叠。
- 相对定位 relative: 如果对一个元素进行相对定位,它将出现在它所在的位置上。然后,可以通过设置垂直 或水平位置,让这个元素“相对于”它的起点进行移动。 在使用相对定位时,无论是 否进行移动,元素仍然占据原来的空间。因此,移动元素会导致它覆盖其它框。
- 绝对定位 absolute: 绝对定位的元素的位置相对于最近的已定位父元素,如果元素没有已定位的父元素,那 么它的位置相对于。absolute 定位使元素的位置与文档流无关,因此不占据空间。 absolute 定位的元素和其他元素重叠。
- 粘性定位 sticky: 元素先按照普通文档流定位,然后相对于该元素在流中的 flow root(BFC)和 containing block(最近的块级祖先元素)定位。而后,元素定位表现为在跨越特定阈值前为相对定 位,之后为固定定位。
- 默认定位 Static: 默认值。没有定位,元素出现在正常的流中(忽略 top, bottom, left, right 或者 z-index 声 明)。 inherit: 规定应该从父元素继承 position 属性的值。
transition和animation的区别
transition是过度属性,强调过度,它的实现需要触发一个事件(比如鼠标移动上去,焦点,点击等)才执行动画。它类似于flash的补间动画,设置一个开始关键帧,一个结束关键帧。
animation是动画属性,它的实现不需要触发事件,设定好时间之后可以自己执行,且可以循环一个动画。它也类似于flash的补间动画,但是它可以设置多个关键帧(用@keyframe定义)完成动画。
CSS3中有哪些新特性
新增各种CSS选择器 (: not(.input):所有 class 不是“input”的节点)
- 圆角 (border-radius:8px)
- 多列布局 (multi-column layout)
- 阴影和反射 (Shadoweflect)
- 文字特效 (text-shadow)
- 文字渲染 (Text-decoration)
- 线性渐变 (gradient)
- 旋转 (transform) 增加了旋转,缩放,定位,倾斜,动画,多背景
隐藏元素的方法有哪些
- 使用display: none; 隐藏dom;
- 使用visibility: hidden; 隐藏dom;
- 使用z-index: -888; 把元素的层级调为负数,然后其他元素覆盖即可;
- 使用opacity: 0; 把元素的透明度调为0,也可以达到隐藏;
- 使用固定定位position: absolute; 把元素定位到看不见的区域;
- 使用transform: scale(0, 0); 把元素缩放为0,也可以实现元素隐藏。
盒子水平垂直居中方法(高频)
-
利用绝对定位,先将元素的左上角通过top:50%和left:50%定位到页面的中心,然后再通过translate来调整元素的中心点到页面的中心
-
利用绝对定位,设置四个方向的值都为0,并将margin设置为auto,由于宽高固定,因此对应方向实现平分,可以实现水平和垂直方向上的居中。该方法适用于盒子有宽高的情况
-
利用绝对定位,先将元素的左上角通过top:50%和left:50%定位到页面的中心,然后再通过margin负值来调整元素的中心点到页面的中心。该方法适用于盒子宽高已知的情况
-
使用flex布局,通过align-items:center和justify-content:center设置容器的垂直和水平方向上为居中对齐,然后它的子元素也可以实现垂直和水平的居中
CSS样式优先级
!important
内联样式(1000)
ID选择器(0100)
类选择器(0010)
元素选择器(0001)
通配符选择器(0000)
JS
JS的数据类型
基本类型:
Number、String、Boolean、Null、undefined、Symbol
复杂类型:
Object、Array、Function
JS的类型检测(高频)
typeof
instanceof
Object.prototype.toString.call()
作用域和作用域链
作用域负责收集和维护由所有声明的标识符(变量)组成的一系列查询,并实施一套非常严格的规则,确定当前执行的代码对这些标识符的访问权限。(全局作用域、函数作用域、块级作用域)。 作用域链就是从当前作用域开始一层一层向上寻找某个变量,直到找到全局作用域还是没找到,就宣布放弃。这种一层一层的关系,就是作用域链。
原型和原型链(高频)
原型:
每个 class都有显示原型 prototype
每个实例都有隐式原型 proto
实例的_ proto_指向对应 class 的 prototype
原型链: 当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么它就会去它的原型对象里找这个属性,这个原型对象又会有自己的原型,于是就这样一直找下去,也就是原型链的概念
特点: JavaScript对象是通过引用来传递的,我们创建的每个新对象实体中并没有一份属于自己的原型副本。当我们修改原型时,与之相关的对象也会继承这一改变。
闭包(高频)
闭包是指有权访问另一个函数作用域中的变量的函数 ——《JavaScript高级程序设计》
当函数可以记住并访问所在的词法作用域时,就产生了闭包,
即使函数是在当前词法作用域之外执行 ——《你不知道的JavaScript》
闭包形成的条件:
函数的嵌套
内部函数引用外部函数的局部变量,延长外部函数的变量生命周期
闭包用途:
能够访问函数定义时所在的词法作用域(阻止其被回收)
私有化变量
模拟块级作用域
创建模块
闭包缺点:会导致函数的变量一直保存在内存中,过多的闭包可能会导致内存泄漏
EventLoop(高频)
JS是单线程的,为了防止一个函数执行时间过长阻塞后面的代码,所以会先将同步代码压入执行栈中,依次执行,将异步代码推入异步队列,异步队列又分为宏任务队列和微任务队列,因为宏任务队列的执行时间较长,所以微任务队列要优先于宏任务队列。微任务队列的代表就是,Promise.then,MutationObserver,宏任务的话就是setImmediate setTimeout setInterval
new运算符的实现机制
首先创建了一个新的空对象
设置原型,将对象的原型设置为函数的prototype对象。
让函数的this指向这个对象,执行构造函数的代码(为这个新对象添加属性)
判断函数的返回值类型,如果是值类型,返回创建的对象。如果是引用类型,就返回这个引用类型的对象。
ES相关
var/let/const
var定义的变量,没有块的概念,可以跨块访问, 不能跨函数访问。 let定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问。 const用来定义常量,使用时必须初始化(即必须赋值),只能在块作用域里访问,且不能修改。
var可以先使用,后声明,因为存在变量提升;let必须先声明后使用。
var是允许在相同作用域内重复声明同一个变量的,而let与const不允许这一现象。
会产生暂时性死区:
https://es6.ruanyifeng.com/#docs/let
es6.ruanyifeng.com/#docs/let
var tmp = 123;
if (true) {
// 存在全局变量tmp,但是块级作用域内let又声明了一个局部变量tmp,导致后者绑定这个块级作用域,
所以在let声明变量前,对tmp赋值会报错
tmp = 'abc'; // ReferenceError
let tmp;
}
map 跟 forEach 的区别
map有返回值 forEach 没有返回值
常用的数组方法
豆豆:JS常用数组方法
12 赞同 · 0 评论文章
ES6常用的新特新
1.新增symbol类型 表示独一无二的值,用来定义独一无二的对象属性名;
2.const/let 都是用来声明变量,不可重复声明,具有块级作用域。存在暂时性死区,也就是不存在变量提升。(const一般用于声明常量);
3.变量的解构赋值(包含数组、对象、字符串、数字及布尔值,函数参数),剩余运算符(...rest);
4.模板字符串(${data});
5.扩展运算符(数组、对象);
6.箭头函数;
7.Set和Map数据结构;
8.Proxy/Reflect;
9.Promise;
10.async函数;
Vue相关
vue 的生命周期
create阶段:vue实例被创建 beforeCreate: 创建前,此时data和methods中的数据都还没有初始化 created: 创建完毕,data中有值,未挂载
mount阶段: vue实例被挂载到真实DOM节点 beforeMount:可以发起服务端请求,去数据 mounted: 此时可以操作Dom
update阶段:当vue实例里面的data数据变化时,触发组件的重新渲染 beforeUpdateupdated
destroy阶段:vue实例被销毁 beforeDestroy:实例被销毁前,此时可以手动销毁一些方法 destroyed
vue 的通讯方式
父子组件通讯 props $emit parent、children Ref
兄弟之间通讯 event bus
跨组件通讯 $attrs、$listeners Provide、inject
vuex
computed与watch
watch 属性监听 是一个对象,键是需要观察的属性,值是对应回调函数,主要用来监听某些特定数据的变化,从而进行某些具体的业务逻辑操作,监听属性的变化,需要在数据变化时执行异步或开销较大的操作时使用
computed 计算属性 属性的结果会被缓存,当computed中的函数所依赖的属性没有发生改变的时候,那么调用当前函数的时候结果会从缓存中读取。除非依赖的响应式属性变化时才会重新计算,主要当做属性来使用 computed中的函数必须用return返回最终的结果 computed更高效,优先使用。data 不改变,computed 不更新。
使用场景computed:当一个属性受多个属性影响的时候使用,例:购物车商品结算功能 watch:当一条数据影响多条数据的时候使用,例:搜索数据
v-if 和 v-for 的优先级
v-for的优先级是高于v-if的,如果两者同时出现的话,那每次循环都会执行v-if,会很浪费性能,我们正确的做法应该是再v-for的外面新增一个模板标签template,在template上使用v-if
$nextTick
nextTick是Vue提供的一个全局API,是在下次DOM更新循环结束之后执行延迟回调,在修改数据之后使用$nextTick,则可以在回调中获取更新后的DOM;
-
Vue在更新DOM时是异步执行的。只要侦听到数据变化,Vue将开启1个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个watcher被多次触发,只会被推入到队列中-次。这种在缓冲时去除重复数据对于避免不必要的计算和DOM操作是非常重要的。nextTick方法会在队列中加入一个回调函数,确保该函数在前面的dom操作完成后才调用;
-
比如,我在干什么的时候就会使用nextTick,传一个回调函数进去,在里面执行dom操作即可;
-
我也有简单了解nextTick实现,它会在callbacks里面加入我们传入的函数,然后用timerFunc异步方式调用它们,首选的异步方式会是Promise。这让我明白了为什么可以在nextTick中看到dom操作结果。
v-for中key的作用
key的作用是为了在diff算法执行时更快的找到对应的节点,提高diff速度,更高效的更新虚拟DOM;
Vue在patch过程中判断两个节点是否是相同节点,key是一个必要条件,渲染一组列表时,key往往是唯一标识,所以如果不定义key的话,Vue只能认为比较的两个节点是同一个,哪怕它们实际上不是,这导致了频繁更新元素,使得整个patch过程比较低效,影响性能;
从源码中可以知道,Vue判断两个节点是否相同时主要判断两者的key和元素类型等,因此如果不设置key,它的值就是undefined,则可能永 远认为这是两个相同的节点,只能去做更新操作,这造成了大量的dom更新操作,明显是不可取的。
keep-alive的实现
作用:实现组件缓存
钩子函数: ”activated “组件渲染后调用 ”deactivated“组件销毁后调用
原理:Vue.js内部将DOM节点抽象成了一个个的VNode节点,keep-alive组件的缓存也是基于VNode节点的而不是直接存储DOM结构。它将满足条件(pruneCache与pruneCache)的组件在cache对象中缓存起来,在需要重新渲染的时候再将vnode节点从cache对象中取出并渲染。
配置属性: include 字符串或正则表达式。只有名称匹配的组件会被缓存 exclude 字符串或正则表达式。任何名称匹配的组件都不会被缓存 max 数字、最多可以缓存多少组件实例
Vuex
Vuex 是一个专为 Vue 应用程序开发的状态管理模式。每一个 Vuex 应用的核心就是 store(仓库)。
Vuex 的状态存储是响应式的;当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新
-
改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation, 这样使得我们可以方便地跟踪每一个状态的变化 Vuex主要包括以下几个核心模块:
State:定义了应用的状态数据
Getter:在 store 中定义“getter”(可以认为是 store 的计算属性),就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来, 且只有当它的依赖值发生了改变才会被重新计算 -
Mutation:是唯一更改 store 中状态的方法,且必须是同步函数
-
Action:用于提交 mutation,而不是直接变更状态,可以包含任意异步操作
-
Module:允许将单一的 Store 拆分为多个 store 且同时保存在单一的状态树中
vue-router 怎么传参
1.id传参
//路由配置
{
path: '/orderDetail/:id',
name: 'orderdetail',
component: () => import('../components/orderDetail.vue'),
meta: { showTabbar: false}
}
this.$router.push({path:/orderDetail/${this.id}
})
2.query传参
this.$router.push({path:/orderDetail
,query:{id:this.id}})
3.pramas传参
this.$router.push({name:orderdetail
,params:{id:this.id}})
插槽
1.普通插槽
2.具名插槽
3.作用域插槽
vue 的双向绑定原理
当一个Vue实例创建时,Vue会遍历data选项的属性,用 Object.defineProperty 将它们转为 getter/setter并且在内部追踪相关依赖,在属性被访问和修改时通知变化。每个组件实例都有相应的 watcher 程序实例,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的 setter 被调用时,会通知 watcher重新计算,从而致使它关联的组件得以更新。
Vue2和Vue3区别
属性监听:
defineProperty: 遍历对象,劫持对象的每一个属性; Proxy: 劫持整个对象,并返回一个代理对象;
对数组方法的支持:
defineProperty: push...等不能监听;Proxy: 可以监听;
兼容:
defineProperty(ES5)兼容性比Proxy(ES6)好。
Vue3
setup函数
-
声明普通类型 ref
-
声明复杂类型 reactive
4.watch 的用法
-
v-model 的用法
-
Vue3双向绑定原理
-
Vue3的生命周期
-
Vue3通讯
-
Vue3.2 setup 语法糖等
webpack相关
常用Loader(高频)
raw-loader:加载文件原始内容(utf-8)
file-loader:把文件输出到一个文件夹中,在代码中通过相对 URL 去引用输出的文件 (处理图片和字体)
source-map-loader:加载额外的 Source Map 文件,以方便断点调试
svg-inline-loader:将压缩后的 SVG 内容注入代码中
image-loader:加载并且压缩图片文件
json-loader 加载 JSON 文件(默认包含)
babel-loader:把 ES6 转换成 ES5
ts-loader: 将 TypeScript 转换成 JavaScript
awesome-typescript-loader:将 TypeScript 转换成 JavaScript,性能优于 ts-loader
sass-loader:将SCSS/SASS代码转换成CSS
css-loader:加载 CSS,支持模块化、压缩、文件导入等特性
style-loader:把 CSS 代码注入到 JavaScript 中,通过 DOM 操作去加载 CSS
postcss-loader:扩展 CSS 语法,使用下一代 CSS,可以配合 autoprefixer 插件自动补齐 CSS3 前缀
vue-loader:加载 Vue.js 单文件组件
常用的Plugin
define-plugin:定义环境变量 (Webpack4 之后指定 mode 会自动配置)
ignore-plugin:忽略部分文件
html-webpack-plugin:简化 HTML 文件创建 (依赖于 html-loader)
web-webpack-plugin:可方便地为单页应用输出 HTML,比 html-webpack-plugin 好用
uglifyjs-webpack-plugin:不支持 ES6 压缩 (Webpack4 以前)
terser-webpack-plugin: 支持压缩 ES6 (Webpack4)
webpack-parallel-uglify-plugin: 多进程执行代码压缩,提升构建速度
mini-css-extract-plugin: 分离样式文件,CSS 提取为独立文件,支持按需加载 (替代extract-text-webpack-plugin)
serviceworker-webpack-plugin:为网页应用增加离线缓存功能
clean-webpack-plugin: 目录清理
oader 和 plugin 的区别
Loader 本质就是一个函数,在该函数中对接收到的内容进行转换,返回转换后的结果。 因为 Webpack 只认识 JavaScript,所以 Loader 就成了翻译官,对其他类型的资源进行转译的预处理工作。
Plugin 就是插件,基于事件流框架 Tapable,插件可以扩展 Webpack 的功能,在 Webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果。
Loader 在 module.rules 中配置,作为模块的解析规则,类型为数组。每一项都是一个 Object,内部包含了 test(类型文件)、loader、options (参数)等属性。
Plugin 在 plugins 中单独配置,类型为数组,每一项是一个 Plugin 的实例,参数都通过构造函数传入
Git相关
git 常用命令
git clone
-
git add .
-
git commit -m
-
git push
-
git pull
-
git branch 查看本地分支
-
git branch -a 查看远程分支
-
git branch -d xxx 删除分支
-
git checkout xxx 切换分支
-
git checkout -b xxx 新建分支并且切换到改分支
-
git branch -m 旧分支名 新分支名 分支重命名
-
git status 查看修改的文件
-
git merge 合并分支
-
git checkout -b xxx origin/xxx 拉去远程分支
-
git log 查看提交记录
网络安全
GET和POST区别(高频)
1.GET在浏览器回退不会再次请求,POST会再次提交请求
2.GET请求会被浏览器主动缓存,POST不会,要手动设置
3.GET请求参数会被完整保留在浏览器历史记录里,POST中的参数不会
4.GET请求在URL中传送的参数是有长度限制的,而POST没有限制
5.GET参数通过URL传递,POST放在Request body中
6.GET参数暴露在地址栏不安全,POST放在报文内部更安全
7.GET一般用于查询信息,POST一般用于提交某种信息进行某些修改操作
8.GET产生一个TCP数据包;POST产生两个TCP数据包
HTTP和HTTPS
http 和 https 的基本概念
http: 是一个客户端和服务器端请求和应答的标准(TCP),用于从 WWW 服务器传输超文本到本地浏览器的超文本传输协议。 https:是以安全为目标的 HTTP 通道,即 HTTP 下 加入 SSL 层进行加密。其作用是:建立一个信息安全通道,来确保数据的传输,确保网站的真实性。
http 和 https 的区别(高频)
1.HTTP
的URL 以http:// 开头,而HTTPS 的URL 以https:// 开头
2.HTTP
是不安全的,而 HTTPS 是安全的
3.HTTP
标准端口是80 ,而 HTTPS 的标准端口是443
4.在OSI
网络模型中,HTTP工作于应用层,而HTTPS 的安全传输机制工作在传输层
5.HTTP
无法加密,而HTTPS 对传输的数据进行加密
6.HTTP
无需证书,而HTTPS 需要CA机构wosign的颁发的SSL证书
http状态码(高频)
200响应成功
-
301永久重定向
-
302临时重定向
-
304资源缓存
-
403服务器禁止访问
-
404服务器资源未找到
-
500 502服务器内部错误 504 服务器繁忙
性能相关
请求跨域
jsonp(利用script标签没有跨域限制的漏洞实现。缺点:只支持GET请求)
CORS(设置Access-Control-Allow-Origin:指定可访问资源的域名)
proxy代理 目前常用方式,通过服务器设置代理
利用h5新特性window.postMessage()
浏览器本地存储
浏览器的本地存储主要分为Cookie、localStorage和sessionStorage。
共同点: 都是保存在浏览器端、且同源的
不同点:
cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递。cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下sessionStorage和localStorage不会自动把数据发送给服务器,仅在本地保存。
存储大小限制也不同,
cookie数据不能超过4K,sessionStorage和localStorage可以达到5M
sessionStorage:仅在当前浏览器窗口关闭之前有效;
localStorage:始终有效,窗口或浏览器关闭也一直保存,本地存储,因此用作持久数据;
cookie:只在设置的cookie过期时间之前有效,即使窗口关闭或浏览器关闭
3.作用域不同
sessionStorage:不在不同的浏览器窗口中共享,即使是同一个页面;
localstorage:在所有同源窗口中都是共享的;也就是说只要浏览器不关闭,数据仍然存在
cookie: 也是在所有同源窗口中都是共享的.也就是说只要浏览器不关闭,数据仍然存在
防抖
多次触发事件,事件处理函数只能执行一次,并且是在触发操作结束时执行。也就是说,当一个事件被触发准备执行事件函数前,会等待一定的时间(这时间是码农自己去定义的,比如 1 秒),如果没有再次被触发,那么就执行,如果被触发了,那就本次作废,重新从新触发的时间开始计算,并再次等待 1 秒,直到能最终执行!
const debounce = (fn, time) => {
let timer = null
return function () {
clearTimeout(timer)
timer = setTimeout(() => {
fn.apply(this)
}, time)
}
}
节流
事件触发后,规定时间内,事件处理函数不能再次被调用。也就是说在规定的时间内,函数只能被调用一次,且是最先被触发调用的那次。
const throttle = (fn, time) => {
let flag = true
return function () {
if (!flag) return
flag = false
setTimeout(() => {
fn.apply(this)
flag = true
}, time)
}
}
优化项目
移除生产环境的控制台打印
第三方库的按需加载
避免css表达式、滤镜,较少DOM操作,优化图片、精灵图,避免图片空链接等
降低请求成本
减少请求数
减少传输体积