前言:参加过今年秋招的同学就会发现今年的前端非常的“内卷”,“内卷”的非常厉害,应届生问的非常非常的难,直接问底层的原理,说真的。刚开始找工作很困难,很心酸,甚至想哭,怀疑自己,但是坚持下去。每一场面试当做一次经历,每一次面试都是一次知识的积累。经历的多了,积累的多了,后面就简单了。加油。一起成长,fight!!!Never give up!
一.HTML ,CSS3,JS
1.js和css加载会不会阻塞
js会阻止dom的解析,但是css不会阻止dom的解析。
2.js和css加载时性能优化
CSS样式表置顶 (阻塞页面渲染)
用link代替@import (1,@import是CSS层面的,不会触发浏览器并发机制;
2,在CSS加载完成后进行的引入。
js脚本置底(因为浏览器有并发限制,所以把js放到下边,减少占用的并发数,使得页面能够更快的渲染出来)
合理使用js的异步加载能力)
3.call 、apply 、 bind
共同点:call、apply、bind都是改变this指向的方法
不同点 apply:和call基本上一致,唯一区别在于传参方式,call传递的是实参列表,apply传递的是数组。
bind:语法和call一模一样,区别在于立即执行还是等待执行,bind不兼容IE6~8
4.盒子模型
1、盒子的组成:内容width+padding+border+margin
2、标准盒子:box-sizing: content-box 大小可随内容的变化而变化
盒子总宽度:width+padding+border+margin
3、边框盒子:box-sizing: border-box 大小不能被内容改变
盒子总宽度:width+margin
5.css3 新特性
1、边框:border-radius box-shadow border-image
2、背景:background-image background-size
3、文本:text-shadow
4、变形:transform
5、过渡:transition
6、动画:animation: name duration iteration-count direction
6.CSS行内元素和块级元素居中
7.JS判断对象(obj)是否为空的方法总结
- 通过JSON.stringify()将json对象转化为json字符串,再判断该字符串是否为”{}”
- for…in 循环判断
- 通过Object.keys()来进行对象**(obj)**是否为空的判断
9.获取原型方法
__proto__
10.对html语义化的理解
1、使页面内容结构化、便于浏览器、搜索引擎解析
2、即使没有css样式也以一种文档格式显示,并且容易阅读
3、搜索引擎的爬虫也依赖于html标记来确定上下文和各个关键字的权重,有利于搜索引擎优化
4、便于阅读、维护和理解
11.图片的预加载
图片的预加载技术使用较为广泛,一般的效果是网页中的图片由模糊变得清晰。
预加载:提前加载图片,当用户需要查看时可直接从本地缓存中渲染。
懒加载:懒加载的主要目的是作为服务器前端的优化,减少请求数或延迟请求数。
两种技术的本质:两者的行为是相反的,一个是提前加载,一个是迟缓甚至不加载。
懒加载对服务器前端有一定的缓解压力作用,预加载则会增加服务器前端压力。
图片懒加载的原理
暂时不设置图片的src
属性,而是将图片的url
隐藏起来,比如先写在data-src
里面,等某些事件触发的时候(比如滚动到底部,点击加载图片)再将图片真实的url
放进src
属性里面,从而实现图片的延迟加载
图片预加载的原理:
核心原理是浏览器请求过的资源会自动缓存。那你用js创建一个看不见的Image标签,浏览器会发出请求,这个过程用户是看不到了。到了页面上真正要显示这张图片的时候,浏览器一检查,哎,原来缓存过来,那就不下载了,直接显示,给用户的感觉就是秒加载
了
12.清除浮动的方式
13.垃圾回收机制
JS的垃圾回收机制是为了以防内存泄漏,内存泄漏的含义就是当已经不需要某块内存时这块内存还存在着,
垃圾回收机制就是间歇的不定期的寻找到不再使用的变量,并释放掉它们所指向的内存。
JS垃圾回收方式
标记清除 引用计数
避免内存泄漏的一些方法
1、减少不必要的全局变量,或者生命周期较长的对象,及时对无用的数据进行垃圾回收。
2、注意程序的逻辑,避免死循环之类的
3、避免创建过多的对象
14.为什么要初始化css样式
1、浏览器的兼容性,每个浏览器设计时都有自己的特性,所以在解析标签的时候就产生一些差异
2、提高编码质量
3、最耗资源、最简单的初始化方式:padding:0 margin:0 border:0
15.水平垂直居中
16.css优化、提高性能的方式
1、尽量将样式写在单独的css文件中,在head元素中引用
2、不使用@import,它会影响文件的加载速度
3、避免使用复杂的选择器,层级越少越好
4、利用css继承减少代码量
5、慎重使用高性能属性:浮动、定位
6、属性值为0时,不加单位
17.typeof 返回的6种数据类型有:
- “boolean”——布尔值
- “string”——字符串
- “number”——数值
- “object”——对象或者null;
- “function”——函数
- “undefined” ——未定义
18.响应式布局方法
1. CSS3-@Media Query
2. 借助原生Javascript
3. 第三方开源框架(比如bootstrap,可以很好的支持浏览器的响应式布局)
4. 百分比,calc()、flex布局 自适
5.通过em,rem来做自适应
19.link和@import区别
1.link属于XHTML标签,而@import完全是CSS提供的一种方式。link标签除了可以加载CSS外,还可以做很多其它的事情,比如定义RSS,定义rel连接属性等,@import就只能加载CSS了。
2.加载顺序的差别。当一个页面被加载的时候(就是被浏览者浏览的时候),link引用的CSS会同时被加载,而@import引用的CSS会等到页面全部被下载完再被加载。所以有时候浏览@import加载CSS的页面时开始会没有样式(就是闪烁),网速慢的时候还挺明显。
3.兼容性的差别。由于@import是CSS2.1提出的所以老的浏览器不支持,@import只有在IE5以上的才能识别,而link标签无此问题。
4.使用dom控制样式时的差别。当使用javascript控制dom去改变样式的时候,只能使用link标签,因为@import不是dom可以控制的。
20.解释下事件冒泡和事件捕获?
事件冒泡:
即同一事件,自子元素冒泡向父元素。(自底向上)
事件捕获:
即同一事件,自父元素捕获至子元素(事件源元素)。(自顶向下)(ie没有捕获事件)
触发顺序:先捕获,后冒泡
21.深浅拷贝的原理?
浅拷贝其实就是当我们新建一个对象A,并且要A来接受重新复制或者引用的对象B的值,如果对象B中的属性是基本数据类型,那么直接复制基本类型的值给A就好;
深拷贝其实就是将一个对象A从内存中完整的拷贝一份出来给到新对象B,并且从堆内存中开辟出一个新的存储空间给到新对象B,这时候如果去改变任何一个对象,互相都不会受到影响,两者完全独立
22.js如何实现重载和多态
重载,函数特征之一,表现为在一个类中同名不同参的方法分别被调用会产生不同的结果。
js本身不支持重载,所以只能通过其他方式实现,arguments检测传参的个数,然后再执行不同的方式
多态,面向对象特征之一,表现为不同对象调用相同方法会产生不同的结果。
prototype
23.图片预加载原理
预加载:提前加载图片,当用户需要查看时可直接从本地缓存中渲染。
预加载会减慢网页打开速度,但是一但打开了话,后面就会很流畅了。
24.如何减少重绘与回流
1.避免逐项更改样式。最好一次性更改style属性,或者将样式列表定义为class并一次性更改class属性。
2.避免循环操作DOM。创建一个documentFragment或div,在它上面应用所有DOM操作,最后再把它添加到window.document。
3.也可以在一个display:none的元素上进行操作,最终把它显示出来。因为display:none上的DOM操作不会引发回流和重绘。
4.避免循环读取offsetLeft等属性。在循环之前把它们存起来。
5.绝对定位具有复杂动画的元素。绝对定位使它脱离文档刘,否则会引起父元素及后续元素大量的回流。
25.flex原理
Flex 是 Flexible Box 的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性。 任何一个容器都可以指定为 Flex 布局。
采用 Flex 布局的元素,称为 Flex 容器(flex container),简称"容器"。它的所有子元素自动成为容器成员,称为 Flex 项目(flex item),简称"项目"
Flex 容器默认存在两根轴:水平的主轴(main axis)和垂直的交叉轴(cross axis)。项目默认沿主轴排列,当然项目的排列方向也可以通过改变属性来控制。
主轴的开始位置(与边框的交叉点)叫做main start,结束位置叫做main end;交叉轴的开始位置叫做cross start,结束位置叫做cross end。单个项目占据的主轴空间叫做main size,占据的交叉轴空间叫做cross size。
26.事件循环机制
JavaScript是单线程语言,在执行JavaScript代码时所有同步任务都在主线程上执行,形成一个执行栈。除了主线程外,还存在一个任务队列存放异步任务,当执行完所有同步任务后,就会从任务队列中逐个取异步任务放入执行栈中执行,而异步任务又分有宏任务和微任务。
异步任务执行顺序:
\1. 先执行微任务,执行完全部的微任务再执行宏任务
\2. 执行宏任务结束后查看有没有产生新的微任务,若产生新的微任务就把新的微任务执行完
\3. 开启下一轮事件循环
也就是有同步任务就先执行同步任务,同步任务执行完就执行异步任务,异步任务先执行微任务,执行完全部微任务再执行宏任务,一直以此循环,这就是事件循环机制
27.src和href的区别
1、请求资源类型不同
(1) href是Hypertext Reference的缩写,表示超文本引用。用来建立当前元素和文档之间的链接。常用的有:link、a。
(2)在请求 src 资源时会将其指向的资源下载并应用到文档中,常用的有script,img 、iframe;
2、作用结果不同
(1)href 用于在当前文档和引用资源之间确立联系;
(2)src 用于替换当前内容;
28.原型链与原型继承
理解原型链其实也很简单:
每个对象都有__proto__
属性指向原型对象,那每个原型对象也有对应的__proto__
属性再指向原型对象的原型对象,这样一层层往上,直到顶端,也就是我们说的 null 的地方,就构成了一条完整的原型链。
原型继承:每一个构造函数都有prototype原型属性,通过构造函数创建出来的对象都继承自该原型属性。所以可以通过更改构造函数的原型属性来实现继承。在JavaScript中,继承的方式有多种,可以一个对象继承另一个对象,也可以通过原型继承的方式进行继承。
29.CSS 的权重和优先级
权重 行内样式 1000
id选择器 100
属性选择器、class或者伪类 10
元素选择器、伪元素 1
通配符 0
优先级
1. 权重相同,写在后面的覆盖前面的
2. 使用 !important 达到最大优先级,都使用 !important 时,权重大的优先级高
30.为什么把异步操作封装在action,把同步操作放在mutations?
- 区分 actions 和 mutations 是为了能用 devtools【是 vue 的浏览器调试 插件】 追踪状态变化。
事实上在 vuex 里面 actions 说到底只是一个函数,在里面想干嘛都可以,只要最后触发 mutation 就行。vuex 真正限制我们的只有 mutation 必须是同步的这一点。
2. 同步的意义在于每一个 mutation 执行完成后都可以对应到一个新的状态。
31.visibility、opacity、display 的差别
visibility:hidden 隐藏元素,位置还存在与页面文档流中,不会被删除,所以会触发浏览器渲染引擎的重绘
opacity:0 将元素设置为透明,位置还存在页面文档流中,不会被删除,所以会触发浏览器渲染引擎的重绘
display:none 隐藏元素,且其位置也不会被保留下来,所以会触发浏览器渲染引擎的回流和重绘。
32、和=区别
1、==:先转换为同一数据类型再进行比较
2、===:先比较数据类型,数据类型不一致直接返回false
二.ES6
1.说说你还知道哪些ES6特性
1.块级作用域的let和const
2.默认参数
直到参数的值为0,因为0在JavaScript中算是false值,它会直接变成后面硬编码的值而不是0本身。在ES6中,我们可以把这些默认值直接放在函数签名中。
3.模版表达式
在反引号包裹的字符串中,使用${NAME}语法来表示模板字符
4.多行字符串
可以直接使用只要充分利用反引号。
5.拆包表达式
{}对应方法可以直接解构
6.改进的对象表达式
在ES6的对象表达式中,我们把getAccounts: getAccounts简化为getAccounts,并且我们还可以用__proto__直接设置prototype
7.箭头函数 =&>
8.Promise
9.class类
10.模块化
import和export运算符来实现了
11.Symbols唯一值
12.generator返回一个迭代器对象
13.for of 遍历
14.set 跟map
2.说var let const 的区别
var定义的变量,没有块的概念,可以跨块访问, 不能跨函数访问。
let定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问。
const用来定义常量,使用时必须初始化(即必须赋值),只能在块作用域里访问,而且不能修改。
3.for in 与for of的区别
for in遍历的是数组的索引(即键名),而for of遍历的是数组元素值。
4.说一下promise
1、抽象的说法:Promise是js中对异步编程进行操作的新的解决方法
2、具体的说法:1)从语法上说:Promise是一个构造函数
从功能上说:Promise对象可以封装一个异步操作,并获取最后异步操作得到的结果
Promise的构造函数接收一个参数,是函数,并且传入两个参数:resolve,reject,分别表示异步操作执行成功后的回调函数和异步操作执行失败后的回调函数。按照标准来讲,resolve是将Promise的状态从 pending置为fullfiled,reject是将Promise的状态置为rejected
5.实现深拷贝
1.loash第三方组件库
2.assgin()伪深拷贝
3.JSON.stringify();
JSON.parse();
4.递归
/ 递归实现一个深拷贝
let obj={
name:'wushikang',
arr:[12,13,14],
strObj:{
weight:'52kg',
height:'180'
},
fn:function(){
console.log('你最棒');
}
}
function deepCopy(obj){
let newObj=null;
if(typeof(obj)==='object'&&obj!==null){
newObj=obj instanceof Array?[]:{}
for(let key in obj){
newObj[key]=deepCopy(obj[key])
}
}else{
newObj=obj
console.log(newObj);
}
return newObj;
}
let obj1=new deepCopy(obj);
console.log(typeof obj1.fn);
6.|| ?? ?.的区别
??空位合并运算符,语法形式为 exp1 ?? exp2
是一个有点类似 ||
的合并符,它仅会在 exp1
的值为 null
或 undefined
时计算并返回 exp2
的值。
?.可选链式取值
本质都是帮助我们减少一些判断值是否是 null
或者 undefined
的条件语句的书写
console.log(obj !== null && obj !== undefined ? obj.prop : undefined)
console.log(obj?.prop);
7.简述ES6中Set、Map集合。
Set类似于数组,key和value是相同
特性:
不允许重复值出现
应用:数组去重
Array.form(new Set(arr))
Map集合类似于对象,key-value对应的集合。
特点:
key值不局限于字符串,可以是任意数据类型
API
let map = new Map()
map.set({name:‘张三’}, [1,2,3])
forEach方法内部回调函数形参位置,先是value,再是k
8.async
async 是一个修饰符,async 定义的函数会默认的返回一个Promise对象resolve的值,因此对async函数可以直接进行then操作,返回的值即为then方法的传入函数
9.commonJS与ES6模块
1、CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
2、CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。
10.防抖节流
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>防抖</title>
</head>
<body>
<input type="text">
<script>
// 防抖:高频触发事件,只想要最后一次事件处理程序内部的执行结果
const input = document.querySelector('input')
input.oninput = debounce(function () {
console.log(this.value);
}, 1000)
// 封装防抖函数
function debounce(fn, delay) {
let timer;
return function () {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
// 业务代码执行地
fn.call(this)
}, delay)
}
}
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>节流</title>
<style>
body {
height: 2000px;
}
</style>
</head>
<body>
<script>
// 节流:控制高频事件的触发次数
window.onscroll = throttle(function () {
console.log('滚动了', this);
}, 1000)
//节流封装函数
function throttle(fn, delay) {
let flag = true;
return function () {
if (flag) {
setTimeout(() => {
fn.call(this)
flag = true
}, delay)
}
flag = false
}
}
</script>
</body>
</html>
11.promise底层代码建议去看一下,很多公司喜欢问这底层的实现原理。
12.数组去重的几种方法
\1. 利用ES6 Set去重(ES6中最常用)
\2. 利用for嵌套,然后splice去重(ES5中常用)
\3. 利用indexOf去重
4.利用sort
5.利用对象的属性不能相同的特点进行去重
6.利用includes
三.jQuery
1.ajax和fetch有什么区别?
(1).ajax是利用对象来请求数据的,而fetch是window的一个方法
(2).ajax基于原生的XHR(XMLHttpRequest)开发,XHR本身的架构不清晰,已经有了fetch的替代方案
(3).fetch写法比ajax更好更方便
(4).fetch不会拒绝HTTP错误状态,只对网络请求报错,对400,500都当做成功的请求
(5).fetch没有原生方法来 监测请求的进度,而XHR可以
2.什么是JSONP
JSONP由两部分组成:回调函数和数据
回调函数是接收到响应时应该在页面中调用的函数,其名字一般在请求中指定。
数据是传入回调函数中的JSON数据。
优点:
能够直接访问响应文本,可用于浏览器与服务器间的双向通信。
缺点:
JSONP从其他域中加载代码执行,其他域可能不安全;
难以确定JSONP请求是否失败。
3.什么是ajax?ajax的同步与异步的区别?
Ajax,直译为“异步的JavaScript与XML技术”,是一种创建交互式网页应用的网页开发技术,用于创建快速动态网页
同步是指:发送方发出数据后,等接收方发回响应以后才发下一个数据包的通讯方式。
异步是指:发送方发出数据后,不等接收方发回响应,接着发送下个数据包的通讯方式。
4.JSON(JavaScriptObject Notation, JS 对象简谱) 是一种轻量级的数据交换格式
1、简单地说,JSON 可以将 JavaScript 对象中表示的一组数据转换为字符串,然后就可以在函数之间轻松地传递这个字符串,或者在异步应用程序中将字符串从 Web 客户机传递给服务器端程序。
2、 JavaScript 很容易解释它
3、JSON 可以表示比名称/值对更复杂的结构。可以表示数组和复杂的对象,而不仅仅是键和值的简单列表。
四.VUE
1.状态机vuex
Vuex有五个核心概念:
state,getters,mutations,actions,modules。
-
state:vuex的基本数据,用来存储变量
-
geeters:从基本数据(state)派生的数据,相当于state的计算属性
-
mutations:提交更新数据的方法,必须是同步的(如果需要异步使用action)。每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。
回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数,提交载荷作为第二个参数。 -
actions:和mutation的功能大致相同,不同之处在于 ==》1. Action 提交的是 mutation,而不是直接变更状态。 2. Action 可以包含任意异步操作。
-
modules:模块化vuex,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理
2. r o u t e 跟 route 跟 route跟router
$route是"路由信息对象",包括path,params,hash,query,fullPath,matched,name等路由信息参数。
$router是"路由实例"对象包括了路由的跳转方法,钩子函数等。
3.如何进行数据绑定
1.$refs
2.v-model
4.双向数据绑定原理
(defineProperty)实现拦截,通过set方法
例如:Object.defineProperty(data,'username',{
set(value){
input.value = value
output.innerText = value
}
})
v-model的原理简单描述
v-model主要提供了两个功能,view层输入值影响data的属性值,data属性值发生改变会更新view层的数值变化。
其核心就是,一方面modal层通过defineProperty来劫持每个属性,一旦监听到变化通过相关的页面元素更新。
另一方面通过编译模板文件,为控件的v-model绑定input事件,从而页面输入能实时更新相关data属性值。
5.vue生命周期
vue实例从创建到挂载到更新,最后销毁,这整个流程叫做vue的生命周 期
生命周期钩子函数
// 初始化构建阶段
beforeCreate vue实例初始化完成之前,完成了vue事件、属性的初始化, 但是访问不到vue实例中的data、methods
created vue实例初始化完成,可以访问实例内部的数据和方法
// 挂载阶段
beforeMount 完成了模板的解析,但是数据没有绑定到模板上
mounted vm.$el虚拟dom替换el Dom,完成了数据绑定。
// 更新阶段
beforeUpdate 数据以及修改,虚拟dom也构建完毕,但是没有渲染到页面 上
updated 更新过后的虚拟dom节点,成功渲染到页面上
// 销毁阶段 this.$destroy()
beforeDestroy vue实例销毁之前,还可以访问实例,闭包的移除,,资源的释放。‘
destroyed vue实例上绑定的事件、监听器、子组件销毁完毕,访问不到 vue实例了
6.事件修饰符
.stop 停止事件冒泡
.prevent 阻止事件默认行为
.capture 在事件捕获阶段执行事件处理函数
.self 只当在 event.target 是当前元素自身时触发处理函数
.once 事件处理函数执行一次后解绑
.passive 滚动事件的默认行为 (即滚动行为) 将会立即触发 ,一般与scroll连用,能够提升移动端的性能
7.watch与computed区别
computed
1. 具有缓存性,页面重新渲染值不变化,计算属性会立即返回之前的计算结果,而不必再次执行函数
当一个属性受多个属性影响的时候就需要用到computed,当一条数据影响多条数据的时候就需要用watch,watch还可以深度监听
watch
1. 监听值的变化,常用于执行异步操作
2. 无缓存性,页面重新渲染时值不变化也会执行
8.祖先组件和后代孙子组件传参
祖先传给孙子:这个高级provide,inject
9.vue多页面传递数据
多页面使用 用状态机vuex
单页面:this.$router.push({
//要跳转的路劲
path: “/people/index”,
//要传递的参数
query: row,
});
接收参数 let id=this. r o u t e . q u e r y . i d ; t h i s . route.query.id; this. route.query.id;this.router.push({
name: ‘product-line-detail’, // 路径
params:{
id: id, // 参数1 name: name // 参数2
}
this.typeId = this.$route.params.id;
10.说一说路由
hash路由和history路由的区别:
1.hash路由在地址栏URL上有#,而history路由没有#,并且更精简
2.进行回车刷新操作,hash路由会加载到地址栏对应的页面,而history路由一般就404报错了
(刷新是网络请求,history路由需要后端支持)。
3.history路由是HTML5新增的API。
hash路由支持低版本的浏览器,而
4.hash的特点在于它虽然出现在了URL中,但是不包括在http请求中,所以对于后端是没有一点影响的,
所以改变hash不会重新加载页面,所以这也是单页面应用的必备。
11.路由中钩子函数的参数
12.vue优势
1、vue是前端三大主流框架之一,三大框架(angularjs/react/vue)
2、vue体积更小(更加轻量级)
3、数据驱动框架,只需要关注底层逻辑,尽量减少对dom的操作
4、生态圈非常广泛,适合初学者(市面很多api介绍)
13.v-for key的作用
key的作用主要是为了高效的更新虚拟DOM。
在用v-for更新已渲染的元素列表的时候,会使用就地复用的策略;
这就是说列表数据修改的时候,他会根据key值去判断某个值是否修改,如果修改了就重新渲染,不然就复用之前的元素
Key可以标识组件的唯一性,为了更好地区别各个组件 key的作用主要是为了高效的更新虚拟DOM保持数据的唯一
不绑定会导致所有列表DOM重新渲染
key也有强制刷新的作用;
14.webpack配置属性
1.webpack如何处理跨域
devServer:{
proxy:{}
}
2.webpack 中loader和plugin区别
Loader直译为"加载器"。Webpack将一切文件视为模块,但是webpack原生是只能解析js文件,如果想将其他文件也打包的话,就会用到loader。 所以Loader的作用是让webpack拥有了加载和解析非JavaScript文件的能力。
Plugin直译为"插件"。Plugin可以扩展webpack的功能,让webpack具有更多的灵活性。 比如压缩打包,优化,不只局限于资源的加载
webpack常用的loader和plugin
loader
样式:style-loader、css-loader、less-loader、sass-loader
文件:file-loader 、url-loader
编译:babel-loader
校验测试:eslint-loader
plugin
html-webpack-plugin、clean-webpack-plugin、extract-text-webpack-plugin
3.webpack编译原理【构建流程】
- 初始化参数,也就是配置信息
- 开始编译:注册所有配置的插件
- 确定入口:从配置的entry入口进入
- 编译模块:调用所有配置的loader对文件进行转换
- 完成模块编译并输出:根据entry配置生成代码块chunk
- 输出完成:输出所有的chunk到文件系统
15.请简述虚拟dom与diff算法
diff算法
1.把树形结构按照层级分解,只比较同级元素。不同层级的节点只有创建和删除操作
2.·给列表结构的每个单元添加唯一的 key 属性,方便比较。
虚拟DOM
Web界面由DOM树(树的意思是数据结构)来构建,当其中一部分发生变化时,其实就是对应某个DOM节点发生了变化。
虚拟DOM就是为了解决浏览器性能问题而被设计出来的。如前,若一次操作中有10次更新DOM的动作,虚拟DOM不会立即操作DOM,而是将这10次更新的diff内容保存到本地一个JS对象中,最终将这个JS对象一次性attch到DOM树上,再进行后续操作,避免大量无谓的计算量。所以,用JS对象模拟DOM节点的好处是,页面的更新可以先全部反映在JS对象(虚拟DOM)上,操作内存中的JS对象的速度显然要更快,等更新完成后,再将最终的JS对象映射成真实的DOM,交由浏览器去绘制。
Diff算法
深度优先遍历,记录差异。在实际代码中,会对新旧两棵树进行一个深度的遍历,每个节点都会有一个标记。每遍历到一个节点就把该节点和新的树进行对比,如果有差异就记录到一个对象中。
平层Diff,只有以下4种情况:
1、节点类型变了,我们将这个过程称之为REPLACE。直接将旧节点卸载并装载新节点。旧节点包括下面的子节点都将被卸载,如果新节点和旧节点仅仅是类型不同,但下面的所有子节点都一样时,这样做效率不高。但为了避免O(n^3)的时间复杂度,这样是值得的。这也提醒了开发者,应该避免无谓的节点类型的变化,例如运行时将div变成p没有意义。
2、节点类型一样,仅仅属性或属性值变了。我们将这个过程称之为PROPS。此时不会触发节点卸载和装载,而是节点更新。
3、文本变了,文本对也是一个Text Node,也比较简单,直接修改文字内容就行了,我们将这个过程称之为TEXT。
4、移动/增加/删除 子节点,我们将这个过程称之为REORDER。
映射成真实DOM,用户交互我们操作数据变化new虚拟DOM。当修改new虚拟DOM,会把newDOM和oldDOM通过diff算法比较,得出diff结果数据表(用4种变换情况表示)。再把diff结果表通过DOM fragment更新到浏览器DOM中。
虚拟DOM的存在的意义?
vdom 的真正意义是为了实现跨平台,服务端渲染,以及提供一个性能还算不错 Dom 更新策略。
Diff算法只是为了虚拟DOM比较替换效率更高。
16.vue中prop验证的type类型有哪几种
props:{
title:String,
likes: Number,
isPublished: Boolean,
commentIds: Array,
author: Object,
callback: Function,
contactsPromise: Promise
}
17.vue组件通信方式 再说理解
父传子
使用props属性:
1.在子组件中定义props数组,数组中设置好数据容器
2.父组件使用子组件时,直接在标签中添加属性并赋值
例如:<btn :attr1="attr1" :obj="post" ></btn>
子传父
使用
e
m
i
t
方法:
1.
子组件中自定义事件
t
h
i
s
.
emit方法: 1.子组件中自定义事件 this.
emit方法:1.子组件中自定义事件this.emit(‘my-event’,this.subMsg,‘hello’)
// 发射数据 参数: 自定义事件名称 发射的数据(作为父组件执行函数的参数)
使用Vuex状态机 /缓存
2.父组件使用子组件时,直接在标签中使用刚刚自定义的事件来父组件的方法。参数就为emit里传过来的参数
例如: <child :msg='msg2' @my-event='handler'></child>
例如:this.$store.state
拓展:拓展运算符 + 辅助函数 ...mapState
18.关于webpack热模块更新的总结如下:
通过webpack-dev-server创建两个服务器:提供静态资源的服务(express)和Socket服务
express server 负责直接提供静态资源的服务(打包后的资源直接被浏览器请求和解析)
socket server 是一个 websocket 的长连接,双方可以通信
当 socket server 监听到对应的模块发生变化时,会生成两个文件.json(manifest文件)和.js文件(update chunk)
通过长连接,socket server 可以直接将这两个文件主动发送给客户端(浏览器)
浏览器拿到两个新的文件后,通过HMR runtime机制,加载这两个文件,并且针对修改的模块进行更新
19.vue是如何进行数据劫持的?
说白了就是通过Object.defineProperty()来劫持对象属性的setter和getter操作,在数据变动时做你想
要做的事
20.混入
混入规则:
1)数据模型中的数据,会进行递归合并,出现同名属性,以组件中的数据为准
2)同名的构造函数会合并成数组,其中的函数都会调用,混入的钩子执行在前,组件的钩子执行在后
3)内部对象的合并,类似于components、methods回合并为一个对象,发生冲突时,以组件中的为准
全局混入
Vue.mixin({})
局部混入
mixins: [mixin]
21.路由守卫:
全局路由守卫
单个路由守卫
组件路由守卫
全局路由守卫
beforeEach(to,from, next)
使用场景
「路由跳转前触发」
作用
「常用于登录验证」
beforeResolve(to,from, next)
使用场景
「在 beforeEach 和 组件内beforeRouteEnter 之后,afterEach之前调用。」
afterEach(to,from)
使用场景
「发生在beforeEach和beforeResolve之后,beforeRouteEnter之前。」
「路由在触发后执行」
单个路由独享
「在beforeEach之后执行,和它功能一样」 ,不怎么常用
{
path:‘/superior’,
component: Superior,
meta:{
icon:‘el-icon-s-check’,
title:‘上级文件’
},
beforeEnter:(to,form,next) =>{
}
}
组件路由守卫
beforeRouteEnter(to,from,next)
beforeRouteUpdate(to,from,next)
beforeRouteLeave(to,from,next)
22.如何实现vue中插件的封装
在其他组件中可以 直接通过 $toast 使用插件
23.v-if和v-for怎么才能一起使用
当 Vue 处理指令时,v-for
比 v-if
具有更高的优先级
24.less中怎么定义使用变量
在 Less 语言中,我们可以使用 @
符号来定义变量,变量分配使用冒号 :
来分配 ,注意是冒号不是等号哟。
@变量名:变量值;
25.vue的内置命令有哪些
-
v-html和v-text
二者的区别是,v-html可以解析html标签,v-text则无法解析
-
v-if条件渲染指令
-
v-show
以用来控制元素或者节点的隐藏与显示
-
v-if与v-show
- 相同点:v-if和v-show都可以控制元素或者节点显示或者隐藏
- 不同点:v-if是通过操作DOM来实现元素的显示与隐藏,当表达式返回值为true时渲染该节点,
- v-show是通过控制css中display属性来决定元素或者节点是否显示。性能开销较小
- v-if是通过节点的销毁和渲染控制显示,性能开销交大,适用于不经常改变的场景,如根据权限控制元素的显示与否,v-show只是简单的css属性切换,适用于频繁切换的场景,
-
v-for列表渲染指令
-
v-bind动态绑定属性
26.对vue缓存的理解
keep-alive是vue内置的一个组件,可以使被它包含的组件处于保留状态,或避免被重新渲染。
27.vue父子组件的生命周期
一、渲染加载过程
父组件(beforeCreate) => 父组件(created) => 父组件(beforeMount) => 子组件(beforeCreate) => 子组件(created) => 子组件(beforeMount) => 子组件(mounted) => 父组件(mounted)
二、子组件更新过程
父组件(beforeUpdate) => 子组件(updated)
三、父组件更新过程
父组件(beforeUpdate) => 父组件(updated)
四、销毁过程
父组件(beforeDestroy) => 子组件(beforeDestroy) => 子组件(destroyed) => 父组件(destroyed)
28.vue数据响应式原理
Vue 的响应式原理是核心是通过 ES5 的保护对象的 Object.defindeProperty 中的访问器属性中的 get 和 set 方法,data 中声明的属性都被添加了访问器属性,当读取 data 中的数据时自动调用 get 方法,当修改 data 中的数据时,自动调用 set 方法,检测到数据的变化,会通知观察者 Wacher,观察者 Wacher自动触发重新render 当前组件(子组件不会重新渲染),生成新的虚拟 DOM 树,Vue 框架会遍历并对比新虚拟 DOM 树和旧虚拟 DOM 树中每个节点的差别,并记录下来,最后,加载操作,将所有记录的不同点,局部修改到真实 DOM 树上。
缺点:Object.defindProperty虽然能够实现双向绑定了,但是还是有缺点,只能对对象的属性进行数据劫持,所以会深度遍历整个对象,不管层级有多深,只要数组中嵌套有对象,就能监听到对象的数据变化无法监听到数组的变化,Proxy就没有这个问题,可以监听整个对象的数据变化,所以用vue3.0会用Proxy代替definedProperty。
29.Vue2和Vue3的区别
vue2的响应式:
核心:
对象:通过defineProperty对对象的已有属性值的读取和修改进行劫持监视/拦截
数组:通过重写数组更新数组的一系列更新元素的方法来实现元素修改的劫持
Object.defineProperty(data, 'count',{
get(){},
set(){}
})
问题:
对象直接新添加的属性或删除已有属性,界面不会自动更新
直接通过下标替换元素或更新length,界面不会自动更新arr[1]={}
vue3的响应式
核心:
通过Proxy(代理):拦截对data任意属性的任意(13种)操作,包括属性值的读写,属性的添加,属性的删除等…
通过 Reflect(反射):动态对被代理对象的相应属性进行特定的操作
Proxy意思就是代理,它的作用是对对象进行拦截,以及数据读取、修改的过滤保护
//假设一个数据对象data,内容为:
var data = {
username: 'Frank',
age: 26
}
现在我们给data创建一个代理proxy
var proxy = new Proxy(data, {set: function(){...}, get: function(){...} })
那么,如果我们需要修改数据,比如正常时:data.username='frank'
有了代理之后是这样:proxy.username='frank'
简单来说,proxy拥有data的属性和权限。
我们在使用Proxy时我们需要用new调用,例如
const p = new Proxy(target, handler)
参数target:是Proxy要包装的目标对象,可以是任意类型的对象,包括原生数组,函数,甚至是另一个代理
参数handler:是一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理p的行为(通俗的说它就是一个处理器,用来监视数据的变化)。它重点的监视方法主要是:handler.get()读取属性值,handler.set()更新属性值,handler.deleteProperty()删除属性值
Reflect是一个内置的对象,它提供拦截JavaScript操作的方法。这些方法与proxy handlers的方法相同。Reflect不是一个函数对象,因此它是不可构造的,不能通过new来调用也不能将它作为一个函数来调用。Reflect的所有属性和方法都是静态的。(通俗的说就是通过反射对象可以把当前的代理对象/目标对象的属性的属性值给反射回去)
new Proxy(date, {
//拦截获取属性值---》读取数据
get(target, prop){
return Reflect.get(target, prop)
},
//拦截设置属性值或添加属性值-----》写入数据
set(target, prop, value){
return Reflect.set(target, prop, value)
}
//拦截删除属性
deleteProperty(target, prop){
return Reflect.deleteProperty(target, prop)
}
})
30.v-text与{{}}与v-html的区别
总结:
用于渲染普通文本,无论何时,绑定的数据对象上 msg属性发生了改变,插值处的内容都会更新。
v-text和{{}}表达式渲染数据,不解析标签。
v-html不仅可以渲染数据,而且可以解析标签。
31.webpack简单理解
webpack是一个前端模块化方案,更侧重模块打包,我们可以把开发中的所有资源(图片、js文件、css文件等)都看成模块,
通过loader(加载器)和plugins(插件)对资源进行处理,打包成符合生产环境部署的前端资源。
webpack中的loader是各种加载器的集合
32.监听器实现
vue中使用 观察者模式【发布+订阅】+ 数据劫持 实现监听数据的变化。
观察者模式【发布+订阅】
定义对象间的一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
即 一个发布者 发布通知后,可以有 任意数目的观察者 订阅并接收通知。
数据劫持
观察者模式已经可以实现数据监听,但是vue做了优化,引入了数据劫持,也就是ES5中的Object.definePropotype方法。该方法能够定义对象属性的 getter 和 setter。【vue3.x使用了ES6中的proxy方法,为对象添加拦截器】
33.解析器实现
解析器的作用:观察UI,视图发生交互时更新数据。具体来说:
1) 解析模板中所有的特定特性,例如:v-model、v-text、{{ }}语法等;
2) 关联数据展示到DOM;
3) 关联事件绑定到DOM;
34.vuex存储和本地存储的区别
1.最重要的区别:vuex存储在内存,localstorage则以文件的方式存储在本地
vuex会随着页面的重启刷新一起重置状态,localstorage(本地存储)则以文件的方式存储在本地,永久保存
2.应用场景:vuex用于组件之间的传值,localstorage则主要用于不同页面之间的传值。
3.永久性:当刷新页面时vuex存储的值会丢失,localstorage不会。
vuex存储在内存,vuex会随着页面的重启刷新一起重置状态,localstorage(本地存储)则以文件的方式存储在本地,永久保存;sessionstorage( 会话存储 ) ,临时保存。localStorage和sessionStorage只能存储字符串类型,对于复杂的对象可以使用ECMAScript提供的JSON.stringify(obj)将其转成字符串,取出来时使用 JSON.parse(str)重新转成对象,而vuex可以存储复杂数据类型。
35.前端性能优化
1)减少http请求
雪碧图
合并样式表和脚本
配置多个域名,会导致域名解析次数增多。此时使用cdn加载,一般cdn域名会缓存到本地,加载速度也快
2)使用服务器端渲染
vue ssr - 》nuxt
3)css放在文件头部,js放在文件底部
4)善用缓存,不重加载资源
5)图片优化
图片懒加载
尽可能使用css代替图片
尽可能使用webp格式图片
6)减少重绘回流
浏览器渲染过程
解析HTML生成DOM树。
解析CSS生成CSSOM规则树。
将DOM树与CSSOM规则树合并在一起生成渲染树。
遍历渲染树开始布局,计算每个节点的位置大小信息。
将渲染树每个节点绘制到屏幕。
什么操作会导致回流?
添加或删除可见的 DOM 元素
元素位置改变
元素尺寸改变
内容改变
浏览器窗口尺寸改变
如何减少回流重绘?
用 JavaScript 修改样式时,最好不要直接写样式,而是替换 class 来改变样式。
浏览器窗口尺寸改变时可以使用防抖
8)事件代理
五.浏览器
1.浏览器输入url后经历的过程
-
在客户端浏览器中输入网址URL。
-
发送到DNS(域名服务器)获得域名对应的WEB服务器的IP地址。
-
客户端浏览器与WEB服务器建立TCP(传输控制协议)连接。
-
客户端浏览器向对应IP地址的WEB服务器发送相应的HTTP或HTTPS请求。
-
WEB服务器响应请求,返回指定的URL数据或错误信息;如果设定重定向,则重定向到新的URL地址。
-
客户端浏览器下载数据,解析HTML源文件,解析的过程中实现对页面的排版,解析完成后,在浏览器中显示基础的页面。
-
分析页面中的超链接,显示在当前页面,重复以上过程直至没有超链接需要发送,完成页面的全部显示。
2.cookie和session有什么区别?
1、存储位置不同
客户端浏览器上。
服务器上。
2、隐私策略不同
cookie对客户端是可见的
session存储在服务器上,对客户端是透明对,不存在敏感信息泄漏的风险。
4、有效期上不同
可以cookie的有效期
session关闭窗口该session就会失效
5、跨域支持上不同
cookie支持跨域名访问。
session不支持跨域名访问。
3.常见状态码
200 表示从客户端发来的请求在服务器端被正常处理了。
204 表示请求处理成功,但没有资源返回。
301 表示永久性重定向。该状态码表示请求的资源已被分配了新的URI,以后应使用资源现在所指的URI。
302 表示临时性重定向。
304 表示客户端发送附带条件的请求时(指采用GET方法的请求报文中包含if-matched,if-modified-since,if-none-match,if-range,if-unmodified-since任一个首部)服务器端允许请求访问资源,
但因发生请求未满足条件的情况后,直接返回304Modified(服务器端资源未改变,可直接使用客户端未过期的缓存)
400 表示请求报文中存在语法错误。当错误发生时,需修改请求的内容后再次发送请求。
401 表示未授权(Unauthorized),当前请求需要用户验证
403 表示对请求资源的访问被服务器拒绝了
404 表示服务器上无法找到请求的资源。除此之外,也可以在服务器端拒绝请求且不想说明理由时使用。
500 表示服务器端在执行请求时发生了错误。也有可能是Web应用存在的bug或某些临时的故障。
503 表示服务器暂时处于超负载或正在进行停机维护,现在无法处理请求。
4.POST和GET的区别?
GET请求参数通过URL传递,POST的参数放在请求体中。
GET产生一个TCP数据包;POST产生两个TCP数据包。对于GET方式的请求,浏览器会把请求头和请求体一并发送出去;而对于POST,浏览器先发送请求头,服务器响应100 continue,浏览器再发送请求体。
GET请求会被浏览器主动缓存,而POST不会,除非手动设置。
GET请求只能进行url编码,而POST支持多种编码方式。
GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
5.HTTP和HTTPS 是什么?
什么是http?
http是一种超文本传输协议,是互联网上应用最为广泛的一种网络协议。所有的WWW文件都必须遵守这个标准。
http也是应用层协议,是为了实现某一类具体应用的协议,并由某一运行在用户空间的应用程序来实现其功能。
HTTP响应也由四个部分组成,分别是:状态行、响应头、空行和响应体。
状态行:协议版本,状态码及状态描述。
响应头:响应头字段主要有connection、content-type、content-encoding、content-length、set-cookie、Last-Modified,、Cache-Control、Expires。
响应体:服务器返回给客户端的内容。
HTTPS,即超文本传输安全协议,是一种通过计算机网络进行安全通信的传输协议
6.HTTPS与HTTP的区别?
HTTP是超文本传输协议,信息是明文传输;HTTPS则是具有安全性的ssl加密传输协议。
HTTP和HTTPS用的端口不一样,HTTP端口是80,HTTPS是443。
HTTPS协议需要到CA机构申请证书,一般需要一定的费用。
HTTP运行在TCP协议之上;HTTPS运行在SSL协议之上,SSL运行在TCP协议之上。
7.浏览器存储
cookie session localstorage
共同点:都是保存在浏览器端
区别:
1、cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递,而sessionStorage和localStorage不会自动把数据发送给服务器,仅在本地保存。
2、存储大小限制不同,cookie数据不能超过4K,同时因为每次http请求都会携带cookie、所以cookie只适合保存很小的数据,如会话标识。sessionStorage和localStorage虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大
3、数据有效期不同,sessionStorage:仅在当前浏览器窗口关闭之前有效;localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;cookie:只在设置的cookie过期时间之前有效,即使窗口关闭或浏览器关闭
4、作用域不同,sessionStorage不在不同的浏览器窗口中共享,即使是同一个页面;localstorage在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的
8.什么情况会出现跨域?如何解决跨域?
跨域场景:
同一域名,不同端口
http://www.demo.com:8000
http://www.demo.com:3000
不同协议
http://www.demo.com
https://www.demo.com
不同域名
http://www.demo1.com
http://www.demo2.com
解决跨域:【方法有多种,着重介绍自己常用的】
1.代理跨域:起一个代理服务器,实现数据的转发
2.nigx反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个服务器。
3.jsonp
4.由后台发起请求。
5.CORS方式
2. jsonp
可以通过动态创建script标签,再请求一个接口地址
原生js
var script = document.createElement('script');
script.type = 'text/javascript';
// 传参并指定回调执行函数为onBack
script.src = 'http://www.demo2.com:8080/login?user=admin&callback=onBack';
document.head.appendChild(script);
// 回调执行函数
function onBack(res) {
alert(JSON.stringify(res));
}
vue中使用vue-jsonp插件实现跨域
this.$jsonp('http://xxx' , params).then((res)=>{
console.log(res)
})
请描述一下cookie,sessionStorage和localStorage的区别
1、localStorage:永久存储会话数据,除非removeItem,否则即使浏览器关闭会话数据也一直存在
2、sessionStorage:临时保存,会话数据只保存到浏览器关闭
3、cookie:可自定义会话数据的失效时间,一般默认浏览器关闭之后失效
9.各个浏览器的内核
Google Chrom内核----Blink内核。
IE浏览器----------------IE内核
Mozilla Firefox -------Firefox内核
Safari-----------------Webkit内核。
Opera----------------Blink内核
-moz代表firefox浏览器私有属性;
-ms代表IE浏览器私有属性;
-webkit代表chrome、safari私有属性;
-o代表Opera私有属性。
10.浏览器的缓存机制
浏览器缓存分为强缓存和协商缓存。缓存的作用是提高客户端速度、节省网络流量、降低服务器压力。
强缓存:浏览器请求资源,如果header中的Cache-Control和Expires没有过期,直接从缓存(本地)读取资源,不需要再向服务器请求资源。
协商缓存:浏览器请求的资源如果是过期的,那么会向服务器发送请求,header中带有Etag字段。服务器再进行判断,如果ETag匹配,则返回给客户端300系列状态码,客户端继续使用本地缓存;否则,客户端会重新获取数据资源。
11.HTTP请求的方法:
HTTP/1.1协议中共定义了八种方法(有时也叫“动作”),来表明Request-URL指定的资源不同的操作方式
1、OPTIONS
返回服务器针对特定资源所支持的HTTP请求方法,也可以利用向web服务器发送‘*’的请求来测试服务器的功能性
2、HEAD
向服务器索与GET请求相一致的响应,只不过响应体将不会被返回。这一方法可以再不必传输整个响应内容的情况下,就可以获取包含在响应小消息头中的元信息。
3、GET
向特定的资源发出请求。注意:GET方法不应当被用于产生“副作用”的操作中,例如在Web Application中,其中一个原因是GET可能会被网络蜘蛛等随意访问。Loadrunner中对应get请求函数:web_link和web_url
4、POST
向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。 Loadrunner中对应POST请求函数:web_submit_data,web_submit_form
5、PUT
向指定资源位置上传其最新内容
6、DELETE
请求服务器删除Request-URL所标识的资源
7、TRACE
回显服务器收到的请求,主要用于测试或诊断
8、CONNECT
HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
12. localStorage设置过期时间只能手动设置。
class Storage{
constructor(name){
this.name = 'storage';
}
//设置缓存
setItem(params){
let obj = {
name:'',
value:'',
expires:"",
startTime:new Date().getTime()//记录何时将值存入缓存,毫秒级
}
let options = {};
//将obj和传进来的params合并
Object.assign(options,obj,params);
if(options.expires){
//如果options.expires设置了的话
//以options.name为key,options为值放进去
localStorage.setItem(options.name,JSON.stringify(options));
}else{
//如果options.expires没有设置,就判断一下value的类型
let type = Object.prototype.toString.call(options.value);
//如果value是对象或者数组对象的类型,就先用JSON.stringify转一下,再存进去
if(Object.prototype.toString.call(options.value) == '[object Object]'){
options.value = JSON.stringify(options.value);
}
if(Object.prototype.toString.call(options.value) == '[object Array]'){
options.value = JSON.stringify(options.value);
}
localStorage.setItem(options.name,options.value);
}
}
//拿到缓存
getItem(name){
let item = localStorage.getItem(name);
//先将拿到的试着进行json转为对象的形式
try{
item = JSON.parse(item);
}catch(error){
//如果不行就不是json的字符串,就直接返回
item = item;
}
//如果有startTime的值,说明设置了失效时间
if(item.startTime){
let date = new Date().getTime();
//何时将值取出减去刚存入的时间,与item.expires比较,如果大于就是过期了,如果小于或等于就还没过期
if(date - item.startTime > item.expires){
//缓存过期,清除缓存,返回false
localStorage.removeItem(name);
return false;
}else{
//缓存未过期,返回值
return item.value;
}
}else{
//如果没有设置失效时间,直接返回值
return item;
}
}
//移出缓存
removeItem(name){
localStorage.removeItem(name);
}
//移出全部缓存
clear(){
localStorage.clear();
}
}
url 统一资源定位符。
13.三次握手的原理
三次握手的最主要目的是保证连接是双工的,可靠更多的是通过重传机制来保证的。
第一次握手:建立连接时,客户端发送syn包(seq=j)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(seq=k),即SYN+ACK包,此时服务器进入SYN_RECV状态。
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。
14.四次挥手
所谓四次挥手(Four-Way Wavehand)即终止TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。在socket编程中,这一过程由客户端或服务端任一方执行close来触发。
(1)第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。
(2)第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。
(3)第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。
(4)第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。
为什么需要TIME_WAIT
六.算法
1.递归
在计算机科学中是指一种通过重复将问题分解为同类的子问题而解决问题的方法
2.快速排序
是对冒泡排序的一种改进,由东尼·霍尔在1960年提出。快速排序是指通过一趟排序将要排序的数据分割成独立的两部分,
其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序
3.冒泡排序
是一种计算机科学领域的较简单基础的排序算法。其基本思路是,对于一组要排序的元素列,依次比较相邻的两个数,将比较小的数放在前面,比较大的数放在后面,如此继续,直到比较到最后的两个数,将小数放在前面,大数放在后面,重复步骤,直至全部排序完成。
4.mvc mvvm区别
1.MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写。
2.MVVM是Model-View-ViewModel的简写。它本质上就是MVC 的改进版。
3.MVVM模式和MVC模式一样,主要目的是分离视图(View)和模型(Model)
MVVM是Model-View-ViewModel的简写。它本质上就是MVC 的改进版。MVVM 就是将其中的View 的状态和行为抽象化,让我们将视图 UI 和业务逻辑分开。
M 数据模型
VM 视图数据模型之间的中间件
V 视图
数据模型中的数据发生更改,传递给视图模型,视图模型再传输给视图层,视图层做相应的页面更新
视图层发生更改,通过视图模型传递给数据模型,数据模型中的数据对应更新
8