理想汽车前端面试经历,面试题分享
面试题目
1、http与https有什么区别
2、HTTP1和HTTP1.1与HTTP2的区别
3、会改变原数组的方法有哪些?
4、深拷贝
5、SSH的原理
6、RSA是什么?什么是非对称加密
7、常见的状态码
8、Vue2和3的区别
9、移动端响应式的原理
10、使用快排实现数组排序?它的时间复杂度是多少
11、事件循环机制
☞ 更多面试题和详解可在腾讯文档获取 docs.qq.com/doc/DZFJPaWZ0a0ZIbVFx
题目详解
一、http与https有什么区别
- 安全性:
- HTTP:是超文本传输协议,数据传输是明文的,没有加密,容易受到中间人攻击。
- HTTPS:在HTTP的基础上加入了SSL/TLS协议,数据传输经过加密,可以保护数据不被窃听和篡改。
- 端口:
- HTTP:默认使用80端口。
- HTTPS:默认使用443端口。
- URL:
- HTTP:URL以http://开始。
- HTTPS:URL以https://开始。
- 搜索引擎优化(SEO):
- 使用HTTPS的网站可能获得更好的搜索引擎排名,因为Google等搜索引擎已经开始将HTTPS作为排名的一个因素。
- 信任和身份验证:
- HTTPS提供了一个身份验证机制,确保用户连接的是他们想要访问的服务器,而不是一个假冒的服务器。
- 成本和资源:
- 实现HTTPS需要购买SSL/TLS证书,可能会增加一些成本和配置工作。
- 浏览器标记:
- 大部分现代浏览器会在地址栏显示一个锁形图标来表示网站使用了HTTPS,而HTTP网站则没有这个图标。
二、HTTP1和HTTP1.1与HTTP2的区别
- 连接使用:
- HTTP/1.0默认每个请求/响应对使用一个新的连接,而HTTP/1.1引入了持久连接(keep-alive),允许在一个TCP连接上发送多个请求/响应,减少了连接建立和关闭的开销 。
- HTTP/2进一步优化了连接使用,支持多路复用,即在单个连接上并行交错发送多个请求和响应,彻底解决了HTTP/1.1中的队头阻塞问题 。
- 数据传输格式:
- HTTP/1.x使用文本格式传输数据,人类可读,但效率相对较低。
- HTTP/2采用了二进制格式,解析更快,减少了传输过程中的开销 。
- 头部处理:
- HTTP/1.x中,头部信息随着每个请求和响应发送,可能会有大量重复数据。
- HTTP/2引入了HPACK压缩算法,对头部信息进行压缩,减少了数据传输量 。
- 安全性:
- HTTP/1.x默认不加密,虽然可以通过HTTPS来加密数据传输。
- HTTP/2推荐使用TLS加密传输,增强了数据传输的安全性 。
- 服务器推送:
- HTTP/1.x中,服务器只能响应客户端明确请求的资源。
- HTTP/2支持服务器推送,即服务器可以主动向客户端发送资源,减少了请求的往返时间 。
- 请求优先级:
- HTTP/1.x不支持请求优先级设置。
- HTTP/2允许设置请求优先级,使得浏览器和服务器可以优化加载顺序,提高用户体验 。
三、会改变原数组的方法有哪些?
以下是一些常见的会改变原数组的方法:
- push() - 向数组末尾添加一个或多个元素,并返回新的长度。
- pop() - 移除数组的最后一个元素,并返回被移除的元素。
- shift() - 移除数组的第一个元素,并返回被移除的元素。
- unshift() - 向数组开头添加一个或多个元素,并返回新的长度。
- splice() - 通过删除或替换现有元素或添加新元素来修改数组的内容。
- fill() - 用一个固定值填充数组中从起始索引到终止索引内的全部元素。
- reverse() - 将数组中的元素顺序颠倒,第一个元素变成最后一个,最后一个变成第一个。
- sort() - 对数组元素进行排序,并原地修改数组(不创建新的数组)。
- copyWithin() - 将数组内部的一部分浅复制到同一数组的另一个位置。
四、深拷贝
深拷贝:将对象完全复制一份,新对象和原对象是两个独立的对象,修改一个对象的属性不会影响另一个对象的属性。常见的深拷贝方法有:
- 使用JSON.parse()和JSON.stringify().它有一些限制,例如不能拷贝函数、undefined、循环引用的对象等。
- 自定义一个递归函数来实现深拷贝,这种方法可以处理循环引用和特殊对象类型。
function deepCopy(source) {
if (typeof source !== 'object' || source === null) {
return source;
}
const target = Array.isArray(source) ? [] : {};
for (const key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = deepCopy(source[key]);
}
}
return target;
}
- 使用第三方库,例如lodash的_.cloneDeep()方法
- 使用structuredClone()(现代浏览器支持):这是一个相对较新的API,可以深拷贝大多数类型的对象。
let originalObj = { a: 1, b: { c: 2 } };
let copiedObj = structuredClone(originalObj);
五、SSH的原理
SSH(Secure Shell)是一种加密的网络协议,用于安全地访问远程计算机。
以下是SSH的一些主要原理和特点:
- 加密传输:SSH使用加密算法来保护数据传输过程中的机密性和完整性,防止数据在传输过程中被窃听或篡改。
- 身份验证:SSH支持多种身份验证方法,包括密码、公钥/私钥对、一次性密码(OTP)、Kerberos 等。
- 公钥/私钥对:SSH最常用的身份验证方式是公钥/私钥对。用户拥有一对密钥,公钥存储在远程主机上,私钥保留在本地。当用户尝试连接到远程主机时,SSH客户端会使用私钥对数据进行签名,远程主机使用公钥验证签名。
- 密钥交换:在SSH连接建立之初,客户端和服务器会进行密钥交换,以协商出一个会话密钥,用于后续通信的加密和解密。
- 端口转发:SSH可以转发本地计算机上的端口到远程计算机,这允许用户访问远程网络上的服务,就像直接连接到远程网络上一样。
- 命令执行:一旦建立了SSH连接,用户可以在远程计算机上执行命令,就像直接在物理机上操作一样。
- 文件传输:SSH提供了文件传输功能(通过SFTP或SCP),允许用户在本地计算机和远程计算机之间安全地传输文件。
- 配置和策略:SSH服务器可以通过配置文件来设置各种安全策略,例如禁用密码认证、限制IP地址、配置密钥使用等。
- 跨平台:SSH可以在多种操作系统平台上运行,包括Linux、Unix、Windows等。
六、RSA是什么?什么是非对称加密
RSA(Rivest-Shamir-Adleman)算法是一种非对称加密技术,RSA算法的安全性很高,但计算量较大,使得它在处理速度上不如对称加密算法。因此,RSA通常用于加密小量数据,如密钥交换、数字签名等,而大量数据的加密则使用对称加密算法。RSA算法广泛应用于网络通信、数字签名、身份验证等领域
非对称加密,又称为公钥加密,是一种加密方法,它使用一对密钥来进行加密和解密操作,这两个密钥是数学上相关的,但在实际应用中是不同的:一个称为公钥,可以公开给任何人;另一个称为私钥,必须由密钥的所有者严格保密。
七、常见的状态码
- 1xx(信息性状态码):
- 100 Continue:继续,客户端可以继续发送请求体(如果存在)。
- 101 Switching Protocols:切换协议,服务器根据客户端的请求切换协议。
- 2xx(成功状态码):
- 200 OK:请求成功。
- 201 Created:已创建,请求成功并且服务器创建了新的资源。
- 202 Accepted:已接受,服务器已接受请求,但尚未处理。
- 204 No Content:无内容,服务器成功处理请求,但没有内容返回。
- 3xx(重定向状态码):
- 300 Multiple Choices:多种选择,请求有多个响应。
- 301 Moved Permanently:永久移动,请求的资源已永久移动到新位置。
- 302 Found:找到,临时移动(以前称为“Moved Temporarily”)。
- 303 See Other:查看其它地址,请求的资源存在另一个URI下。
- 304 Not Modified:未修改,自从上次请求后,资源未被修改。
- 4xx(客户端错误状态码):
- 400 Bad Request:错误请求,请求无法理解或参数有误。
- 401 Unauthorized:未授权,请求需要用户验证。
- 403 Forbidden:禁止访问,服务器理解请求但拒绝执行。
- 404 Not Found:未找到,服务器上未找到请求的资源。
- 5xx(服务器错误状态码):
- 500 Internal Server Error:内部服务器错误,服务器内部错误,无法完成请求。
- 501 Not Implemented:未实现,请求的功能未被服务器实现。
- 502 Bad Gateway:错误网关,服务器作为网关或代理时,从上游服务器收到无效响应。
- 503 Service Unavailable:服务不可用,服务器当前无法使用(过载或停机维护)。
- 504 Gateway Timeout:网关超时,网关或代理在等待上游服务器响应时超时。
八、Vue2和3的区别
- 组合式 API(Composition API):Vue.js 3.0引入了Composition API,提供了一种新的组织组件逻辑的方式。与Vue.js 2.0的Options API相比,Composition API更加灵活、可复用,并且可以更好地组织和共享逻辑代码。
- 更好的响应式系统:Vue.js 3.0对响应式系统进行了重写,使用了Proxy代理对象来实现数据变化的监听和依赖追踪。相较于Vue.js 2.0使用的Object.defineProperty,Proxy具有更好的性能和更丰富的功能,使得Vue.js 3.0的响应式系统更加强大和灵活。
- 性能优化:Vue.js 3.0在性能方面进行了一系列的优化,包括使用了更快的虚拟DOM算法(Fragments和Teleport)、优化的编译器、懒加载组件等。这些改进使得Vue.js 3.0相对于2.0在性能方面有显著的提升。
- 体积优化:Vue.js 3.0采用了模块化的设计,可以实现按需引入,只加载需要的部分,从而减小应用的体积。此外,Vue.js 3.0还对Tree-shaking进行了优化,可以更有效地剔除无用代码,减少应用的大小。
- TypeScript支持:Vue.js 3.0对TypeScript提供了更好的支持,包括提供了更好的类型推断、增强的类型检查等功能,使得在使用TypeScript开发Vue.js应用更加方便和安全。
九、移动端响应式的原理
主要是通过灵活的布局和CSS媒体查询来确保网页在不同设备和屏幕尺寸上都能提供良好的用户体验
- 流体布局(Fluid Layouts):
- 使用相对单位(如%、vw、vh)而非绝对单位(如px)设置元素的宽度和高度,使布局能够根据屏幕尺寸的变化而伸缩。
- 媒体查询(Media Queries):
CSS媒体查询允许开发者根据设备的特性(如屏幕宽度、分辨率等)应用不同的CSS样式规则。这使得页面可以根据不同的屏幕尺寸加载不同的样式。
- 视口(Viewport):
通过<meta name="viewport" content="width=device-width, initial-scale=1">
来控制布局在移动端浏览器中的初始缩放。width=device-width使得布局宽度等于设备的屏幕宽度,initial-scale=1设置初始缩放比例为1。
十、使用快排实现数组排序?它的时间复杂度是多少
- 选择基准元素(Pivot):从数组中选择一个元素作为基准。不同的选择方法会影响算法的性能。
- 分区操作(Partitioning):重新排列数组,使得所有比基准小的元素都在基准的左边,所有比基准大的元素都在基准的右边。
- 递归排序:对基准左边和右边的子数组分别进行快速排序。
- 组合:由于快速排序是就地排序,一旦子数组被排序,整个数组也就排序完成了。
function quickSort(arr, low = 0, high = arr.length - 1) {
if (low < high) {
// 执行分区操作
const pivotIndex = partition(arr, low, high);
// 对基准左边的子数组进行快速排序
quickSort(arr, low, pivotIndex - 1);
// 对基准右边的子数组进行快速排序
quickSort(arr, pivotIndex + 1, high);
}
return arr;
}
// 选择最右侧的元素作为基准
function partition(arr, low, high) {
const pivot = arr[high];
let i = low; // `i` 指向比基准小的区域的最后一个元素
for (let j = low; j < high; j++) {
// 将小于基准的元素移动到左侧
if (arr[j] < pivot) {
[arr[i], arr[j]] = [arr[j], arr[i]]; // 交换元素
i++;
}
}
// 将基准元素放到它最终的位置
[arr[i], arr[high]] = [arr[high], arr[i]];
return i; // 返回基准的索引
}
// 使用示例
const array = [10, 7, 8, 9, 1, 5];
console.log(quickSort(array));
时间复杂度是O(nlogn)
十一、事件循环机制
事件循环(Event Loop)是 JavaScript 运行时环境用来处理异步操作的机制。它负责管理 JavaScript 代码的执行顺序,使得异步操作能够以非阻塞的方式进行。
事件循环的主要思想是将任务分为不同的队列,然后按照特定的规则来执行这些队列中的任务。在浏览器环境中,事件循环由浏览器的主线程控制,而在 Node.js 环境中,则由 Node.js 的事件驱动模型管理。
下面是事件循环的基本步骤:
- 执行同步任务:从调用栈(执行上下文栈)中取出位于栈顶的同步任务执行。
- 执行微任务(Microtask)队列:在执行同步任务过程中,如果遇到微任务(如 Promise 的回调函数、queueMicrotask 方法等),则将其添加到微任务队列中。
- 执行宏任务(Macrotask)队列:当同步任务和微任务队列都为空时,事件循环会从宏任务队列中取出一个任务执行。常见的宏任务包括 setTimeout、setInterval、requestAnimationFrame、I/O 操作等。
- 更新渲染:在浏览器环境中,如果当前任务完成后需要更新页面的渲染,会执行渲染操作。
- 重复上述步骤:事件循环会不断重复执行上述步骤,直到所有任务都被处理完毕