cvte 前端一面 凉经
原文面试题地址:https://www.nowcoder.com/discuss/353159272857018368?sourceSSR=search
1. vuex原理
和vuerouter的原理差不多
2. vuerouter的原理
-
首先在main.js中,import router from ‘./router’ 引入在router文件夹下面的index.js
-
在index.js中,然后执行import VueRouter from ‘./MyVueRouter.js’
-
./MyVueRouter.js为自己实现的vuerouter文件
-
然后 Vue.use(VueRouter),当使用Vue.use(VueRouter),会自动执行./MyVueRouter.js文件里面的install(Vue)方法
括号里面的Vue是vue提供的参数
5.然后就执行new VueRouter
const router = new VueRouter({
mode: 'hash',
base: process.env.BASE_URL,
routes
})
6.然后就会执行./MyVueRouter.js 下面的constructor方法,在构造器方法里面接收new时候传进来的参数,然后再定义一个变量用来存储path和component的映射关系,然后再利用vue的双向绑定监听hash值的变化
7.然后就会执行main.js里面new Vue,到了beforcreate的时候就会执行MyVueRouter.js里面的beforeCreate方法,然后完成了路由的初始化init()
8.init()
init() {
this.createRouteMap(); // 根据 routes 拿到 url => 组件 对应关系
this.initComponent(); // install 在 new Vue() 之前,双向绑定 curRoute 数据在 new Vue 创建, 挪到 init 中处理
this.listenUrlChange();//初始化监听
}
//建立path 和 组件之间的映射
createRouteMap() {
this.options.routes.forEach((route) => {
this.routeMap[route.path] = route.component;
});
}
initComponent() {
// <router-view></router-view>
_Vue.component("RouterView", {
render: (h) => {
let component = this.routeMap[this.app.curRoute];
return h(component);
},
});
// <router-link to="/about">foo</router-link>
_Vue.component("RouterLink", {
props: { to: String },
render(h) {
// h(tag, options, children) 子元素使用默认插槽,这里使用简单 hash 模式 #/about
let options = { attrs: { href: `#${this.to}` } };
return h("a", options, [this.$slots.default]);
},
});
}
listenUrlChange() {
// 首次进入
window.addEventListener("load", () => {
// /about 或者 /
this.app.curRoute = window.location.hash.slice(1) || "/";
});
// hash 改变
window.addEventListener("hashchange", (e) => {
console.log(e);
// 除了 location 外,还可以用 HashChangeEvent 中的参数 { newURL: "http://localhost:8080/#/about" }
let hashPath = new URL(e.newURL).hash;
hashPath = hashPath[0] === "#" ? hashPath.substring(1) : "/"; // http://localhost:8080/#/
this.app.curRoute = hashPath;
});
}
3.http1.0
HTTP/1.0是最早版本的HTTP协议,于1996年发布。以下是HTTP/1.0的主要特点和限制:
- 单连接单请求:在HTTP/1.0中,每个请求需要建立一个新的TCP连接,而在接收到响应后,连接会立即关闭。这导致了每个请求都需要经历TCP连接的建立和关闭过程,增加了网络开销和延迟。
- 无状态:HTTP/1.0是无状态协议,每个请求都是独立的,服务器不会保留任何关于客户端的状态信息。这意味着每个请求都需要包含完整的信息,如请求头部和身份验证信息。
- 请求-响应模型:HTTP/1.0采用了简单的请求-响应模型,客户端发送请求,服务器返回响应。在接收到响应之前,客户端无法发送新的请求。
- 文本传输:HTTP/1.0使用文本格式传输数据,请求和响应的头部和正文都是以纯文本的形式发送。这种文本格式相对较为简单,但也限制了性能和扩展性。
- 缺乏性能优化:HTTP/1.0在性能方面存在一些限制。由于每个请求都需要单独建立连接,并且每个请求只能按顺序进行处理,导致请求的并发性和效率较低。
尽管HTTP/1.0存在这些限制,但它为Web的发展奠定了基础,并且在很长一段时间内被广泛使用。随着互联网的发展和对更高性能的需求,HTTP/1.1和HTTP/2.0等后续版本进行了进一步改进和优化。
4.http2.0
HTTP/2.0(或称为HTTP/2)是HTTP协议的最新版本,于2015年发布。它是HTTP/1.1的继任者,带来了许多性能改进和新特性。以下是HTTP/2.0的主要特点:
- 多路复用(Multiplexing):HTTP/2.0引入了多路复用功能,允许在单个TCP连接上同时发送多个请求和接收多个响应。这消除了HTTP/1.x中每个请求都需要建立独立连接的开销,提高了请求的并发性和性能。
- 二进制分帧(Binary Framing):HTTP/2.0使用二进制分帧来传输数据,将请求和响应拆分为多个帧,并对它们进行编码和解码。这种二进制格式相对于HTTP/1.x的文本格式更加高效,减少了数据传输的大小,并且可以更好地支持压缩和优化。
- 头部压缩(Header Compression):HTTP/2.0使用了HPACK算法对请求和响应的头部进行压缩。由于HTTP/1.x每个请求都需要携带完整的头部信息,这可能会导致冗长的头部,增加了数据传输的大小。HTTP/2.0的头部压缩减少了冗余信息,减小了数据传输量。
- 服务器推送(Server Push):HTTP/2.0支持服务器推送功能,服务器可以在客户端请求之前主动将相关资源推送给客户端。这减少了客户端发起额外请求的需求,提高了页面加载速度。
- 流量优化和优先级(Flow Control and Prioritization):HTTP/2.0引入了流控制机制,使服务器能够控制发送数据的速率,避免了客户端的过载或拥塞。此外,HTTP/2.0还支持请求的优先级设置,使服务器可以优先处理重要的请求。
总的来说,HTTP/2.0在性能和效率方面进行了重大改进,提供了更快的加载速度、更低的延迟和更高的并发性。通过引入多路复用、二进制分帧、头部压缩和服务器推送等新特性,HTTP/2.0使得网络通信更加高效、可靠和灵活。
5.TCP和UDP
TCP (Transmission Control Protocol) 和 UDP (User Datagram Protocol) 都是在网络通信中使用的传输层协议,它们有以下区别:
- 连接导向 vs. 无连接:TCP是一种面向连接的协议,它在通信之前需要建立连接,确保可靠的数据传输,然后再终止连接。UDP是一种无连接的协议,每个数据包都是独立的,发送方和接收方之间没有建立持久的连接。
- 可靠性:TCP提供可靠的数据传输,通过使用序列号、确认和重传等机制来确保数据的完整性和顺序性。如果数据包丢失或损坏,TCP会重新发送它们,以确保所有数据都被正确接收。UDP不提供可靠性保证,它发送数据后不会等待确认,也不会进行重传。因此,UDP可能会丢失数据包,但也因此具有较低的延迟。
- 有序性:TCP保证数据的有序传输,接收方会按照发送方的顺序重新组装数据。UDP没有内置的有序性机制,接收方接收到的数据包的顺序可能与发送顺序不同。
- 拥塞控制:TCP具有拥塞控制机制,它会根据网络状况动态调整发送速率,以避免网络拥塞。UDP没有拥塞控制,发送方以固定速率发送数据,不会根据网络状况进行调整。
- 数据量和开销:TCP使用较大的报文头部来管理连接状态、序列号等信息,这增加了每个数据包的开销。UDP的报文头部较小,因此数据包的开销相对较小。
根据这些特点,选择使用TCP还是UDP取决于具体的应用场景。如果需要可靠的数据传输和有序性,TCP是更好的选择。如果对数据传输的实时性要求较高,而对丢失一些数据包不敏感,可以选择UDP。常见的应用场景中,Web浏览器使用TCP进行网页加载,而音频和视频流传输则经常使用UDP,因为它们需要实时性而可以容忍一些丢失。
6.TCP三次握手和四次挥手
为什么建立连接需要三次握手
三次握手:
1.客户端先发送一个数据包询问服务器能否与你建立连接(这个数据包被称为SYN包)
2.服务器收到之后同意连接,则会回复SYN+ACK包
3.客户端收到之后会回复一个ACK包。 以上就是三次握手建立连接
假设不使用三次握手而使用两次握手会发生什么呢?
1.假设客户端要建立连接,先发送一个建立连接的数据包SYN,但是因为网络拥塞而导致第一个SYN包没有到达服务器,这时候客户端又会发送第二个SYN包给服务器建立连接,假设服务器收到了第二个SYN包,然后回复ACK+SYN包,表示成功建立连接。而突然这个时候因为前面网络拥塞而迟到的第一个SYN包到达服务器,那么服务器也会回复一个ACK+SYN包,这时候服务器就会以为有两个请求,但是实际上只有一个。
为什么释放连接需要四次挥手
1.客户端发送主动发送关闭连接请求(FIN包),表示要关闭连接。
2.服务器收到了FIN包,然后就会回复ACK包给客户端,表示已经收到了。此时服务端还是可以发送数据的,当服务端已经把所有数据发送完成之后,就进入3
3.然后服务器就会发送FIN包给客户端
4.客户端收到之后就会回复ACK包表示已经收到了,服务端收到了ACK包就会立刻关闭连接。经过超时等待时间后,客户端就会关闭连接。 为什么客户端需要等待超时时间,因为这是为了保证对方已经收到了ACK包,因为假设客户端发送了ACK包就关闭了,那么ACKK包如果丢失了的话服务端就关闭不了了。
7.css盒子模型
盒模型的主要组成部分如下:
- 内容(content):盒子内部的实际内容,比如文本、图像等。它的大小由元素的宽度(width)和高度(height)属性决定。
- 内边距(padding):内容与边框之间的空白区域。可以使用padding属性来设置内边距的大小。内边距会增加盒子的尺寸。
- 边框(border):包围内容和内边距的线条或样式。可以使用border属性来设置边框的样式、宽度和颜色。
- 外边距(margin):盒子与其他元素之间的空白区域。可以使用margin属性来设置外边距的大小。外边距会影响元素在页面布局中的位置。
盒子模型主要分为两种
标准盒模型(content-box)也叫 W3C 盒子模型(标准盒模型)
标准盒模型:边框和内边距额外增加盒子的尺寸。
IE 盒子模型(怪异盒模型)(border-box)
宽度(width)和高度(height)包括了内容区域、边框和内边距,边框和内边距减少了可用于展示内容的空间。
8.实现四个块的四等分
实现思路:
给父盒子设置成flex布局,然后下面的4个子盒子使用 下面代码就可以四等分了
flex:1
9. display:none, visibility:hidden的区别,开发时候应用场景
在开发中,display: none
和visibility: hidden
是用于隐藏元素的CSS属性
display: none
的作用是完全从页面中移除元素,并且在页面布局中不占据任何空间。这意味着隐藏的元素不会影响周围元素的布局和位置。当应用display: none
时,元素会被完全隐藏,无法看到或与其进行交互,包括元素的内容、边框和内外边距都不会显示。它可以通过修改CSS样式或使用JavaScript来动态切换元素的可见性。
visibility: hidden
则是将元素隐藏,但它仍然占据页面中的空间。被隐藏的元素仍然存在于文档流中,它只是不可见,但它会保留它在布局中所占据的空间。这意味着周围的元素仍然会在布局中考虑到隐藏元素的空间。元素的内容、边框和内外边距仍然存在,只是不可见。与display: none
不同,使用visibility: hidden
不会影响布局,因为隐藏的元素仍然保持其原始大小和形状。
10.闭包是什么,闭包的应用
闭包就是内层函数+外层变量的引用
作用
- 保护变量:通过闭包可以创建一个私有的作用域,使得内部变量不会被外部访问和修改。这在模块化开发中非常有用,可以隐藏实现细节,只暴露需要提供的接口。
- 延长局部变量的生命周期:当外部函数执行结束时,其内部函数依然可以访问和使用外部函数的变量。这对于需要长时间存储数据或延长变量生命周期的场景很有帮助,例如在事件处理函数中保留对一些重要数据的引用。
例如 节流和防抖就是闭包的使用场景
闭包使用不当可能会导致内存泄漏,因为内部函数持有对外部函数作用域的引用,导致外部函数中的变量无法被垃圾回收。因此,在使用闭包时,需要注意管理内存和避免不必要的引用。
11.事件循环
12.事件流
事件捕获阶段 处于目标阶段 事件冒泡阶段
<body>
<button>
<span>我是按钮</span>
</button>
</body>
使用dom0级事件处理程序ele.onclick = function(){}
当点击我是按钮的时候,会在控制台输出 我是按钮 我是button 我是body ,所以可以是处于冒泡阶段的
使用dom2级事件处理程序 ele.addEventListener('click',function(){},(false或者true))默认为false
当为false是时处于事件冒泡阶段 当为true的时候为事件捕获阶段
13.csrf与xss攻击
CSRF(Cross-Site Request Forgery)和XSS(Cross-Site Scripting)都是常见的网络安全漏洞,可以用于对Web应用程序进行攻击。虽然它们都涉及到跨站点攻击,但是它们的工作原理和目标有所不同。
- CSRF(跨站点请求伪造): CSRF攻击利用用户在已认证的Web应用程序上执行未经授权的操作。攻击者通过欺骗用户访问恶意网站或点击包含恶意代码的链接,从而在用户的浏览器中触发未经授权的请求。这些请求会携带用户的身份验证凭据,以便攻击者可以代表用户执行特定操作,如更改密码、发送付款请求等。
防御CSRF攻击的常见方法包括:
- 验证请求来源:Web应用程序可以检查每个请求的来源是否是合法的站点,并仅接受来自受信任站点的请求。
- 使用随机令牌(CSRF令牌):Web应用程序可以在用户会话中生成一个随机令牌,并将其包含在表单或请求中。服务器在接收到请求时验证令牌的有效性,如果令牌无效,则拒绝请求。
- XSS(跨站点脚本): XSS攻击允许攻击者将恶意脚本注入到Web应用程序的页面中,使其在用户的浏览器上执行。攻击者可以通过操纵输入字段、URL参数或其他用户可控制的输入来注入恶意脚本。一旦用户在受影响的页面上加载了恶意脚本,该脚本可以执行各种操作,如窃取用户的会话令牌、篡改页面内容、重定向用户等。
防御XSS攻击的常见方法包括:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NecCo918-1686225995519)(D:\系统默认\桌面\1.jpg)]
14.cookie
Cookie是一种小型的文本文件,由网站存储在用户的计算机或设备上。它们主要用于跟踪和存储与用户相关的信息,以提供个性化的网站体验。当用户访问一个网站时,网站会向用户的浏览器发送一个包含cookie的请求,并且浏览器会将该cookie存储在用户的计算机或设备上。
每个cookie都包含一些键值对,用于存储特定的信息,例如用户的偏好设置、登录状态、购物车内容等。当用户再次访问同一网站时,浏览器会将相关的cookie发送回服务器,以便网站可以根据之前存储的信息进行相应的操作和提供个性化的内容。
Cookie可以分为会话cookie和持久cookie。会话cookie在用户关闭浏览器时会被删除,而持久cookie会在特定时间段内保留在用户的计算机或设备上。网站使用cookie的目的可以包括但不限于:记住用户的登录状态、跟踪用户的浏览行为、提供个性化的广告和内容等。
需要注意的是,由于cookie可以存储个人身份信息或跟踪用户的浏览行为,一些法规和隐私政策要求网站在使用cookie时需事先告知用户并获得其同意。
15…输入一个url…
16.回流和重绘
主要过程
回流,重点在于流,倾向于结构调整,对性能影响更大
重绘,重点在于绘,倾向于样式的调整,对性能的影响较小
回流的代价比重绘更高
回流一定会触发重绘,重绘不一定会触发回流
回流
浏览器对回流和重绘的优化
浏览器维护这一个回流和重绘的队列,当达到阈值之后,就会触发回流和重绘,然后浏览器就会清空队列,批处理这些操作。
当我们访问以下属性或者方法时,浏览器会立刻清空队列,执行回流和重绘返回正确的值
如何避免回流
影响较小
回流的代价比重绘更高
回流一定会触发重绘,重绘不一定会触发回流
回流
[外链图片转存中…(img-BsODbLtI-1686225995519)]
浏览器对回流和重绘的优化
浏览器维护这一个回流和重绘的队列,当达到阈值之后,就会触发回流和重绘,然后浏览器就会清空队列,批处理这些操作。
当我们访问以下属性或者方法时,浏览器会立刻清空队列,执行回流和重绘返回正确的值
[外链图片转存中…(img-fWRSNPZd-1686225995520)]