js面试八股
es6里的箭头函数和普通函数有什么区别?
无法用作构造函数
普通函数:可以通过 new 关键字作为构造函数使用,创建新的对象实例。
箭头函数:不能作为构造函数,使用 new 调用箭头函数会抛出错误。
const NormalFunction = function () {
this.name = "Normal";
};
const ArrowFunction = () => {
this.name = "Arrow";
};
const normalInstance = new NormalFunction(); // 正常工作
const arrowInstance = new ArrowFunction(); // 报错:TypeError: ArrowFunction is not a constructor
new关键字实例化一个函数的构造器是个什么样的过程?
new
关键字的作用是创建一个新的对象,并将其与构造函数的原型链关联起来,同时允许构造函数通过 this
对新对象进行初始化。
讲一下js里的原型链是一种什么机制?
JavaScript 中的原型链(Prototype Chain)是一种用于实现继承和共享属性的机制。它允许对象通过一个内部的链接([[Prototype]]
)访问另一个对象的属性和方法。在 JavaScript 中,每个对象都有一个内部属性 [[Prototype]]
,它指向另一个对象,通常被称为该对象的“原型”。这个原型对象本身也有自己的原型,如此递归形成一个链状结构,这就是所谓的“原型链”。
工作原理:
当访问一个对象的属性或方法时,JavaScript 会按照以下步骤查找:
-
自身属性查找:首先在对象自身的属性中查找。
-
原型链查找:如果在对象自身中找不到,JavaScript 会沿着原型链向上查找,直到找到该属性或方法,或者到达原型链的末端(即
null
)。 -
原型链的结构可以表示为:
对象 -> 对象的原型 -> 原型的原型 -> ... -> null
-
原型链的用途
继承:通过原型链,对象可以继承原型对象的属性和方法。这是 JavaScript 中实现类式继承的主要方式。
共享属性和方法:原型链允许多个对象共享原型对象上的属性和方法,从而节省内存。
浏览器的同源策略是一种什么机制?
浏览器的同源策略(Same-Origin Policy)是一种重要的安全机制,用于限制不同来源(origin)的文档或脚本之间的交互能力。
同源策略中的“同源”是指两个资源的协议(scheme)、域名(host)和端口(port)完全一致。如果这三个部分有任何一个不同,那么这两个资源就被认为是“跨源”的。
-
协议:
http://
、https://
等。 -
域名:
example.com
、sub.example.com
等。 -
端口:
80
(HTTP 默认端口)、443
(HTTPS 默认端口)、8080
等。
同源策略的主要作用是限制一个源(origin)的文档或脚本对另一个源的资源的访问。具体来说,它会阻止以下行为:
跨源读取数据:一个网页的脚本不能读取另一个不同源网页的文档内容(如 DOM、localStorage、sessionStorage 等)。
例如,http://example.com 的脚本不能直接读取 https://example.com 的页面内容。
跨源发送请求:默认情况下,浏览器会阻止脚本向不同源的服务器发送请求(如 XMLHttpRequest 或 fetch)。
例如,http://example.com 的脚本不能直接向 http://another.com 发送请求。
跨源操作 Cookie:浏览器会限制对不同源的 Cookie 的访问,防止恶意网站窃取用户的登录信息。 -
为什么需要同源策略?
同源策略的主要目的是防止跨站脚本攻击(XSS)和跨站请求伪造(CSRF),保护用户的隐私和数据安全。
假设用户登录了银行网站https://bank.com
,并且银行网站的 Cookie 中存储了用户的会话信息。如果同源策略不存在,恶意网站http://evil.com
可以通过脚本读取https://bank.com
的 Cookie,从而窃取用户的会话信息并进行非法操作。
不符合同源策略会发生什么问题(衍生讲解解决跨域问题的方法)
当不符合同源策略时,浏览器会阻止某些跨域操作,导致以下问题:
-
无法读取跨域资源:JavaScript 无法访问不同源页面的 DOM 或从其他源的服务器读取数据。
-
HTTP 请求被阻止:使用
XMLHttpRequest
或fetch
发起的跨域请求会被浏览器拦截。 -
Cookie 和 Session 无法共享:跨域请求无法携带或读取其他源的 Cookie 和 Session。
解决跨域问题的方法
1. CORS(跨源资源共享)
CORS 是一种服务器端机制,允许服务器明确声明哪些外部域名可以访问其资源。
JSONP(JSON with Padding)
JSONP 是一种古老的跨域技术,通过 <script>
标签的 src
属性动态加载跨域资源。
Window.postMessage
Window.postMessage
是一种现代的跨域通信方法,允许不同源的窗口之间安全地发送消息。
Nginx 反向代理
通过 Nginx 配置代理服务器,将跨域请求转发到目标服务器。
后端设置跨域
在后端框架中配置全局或局部的跨域策略。
可以讲一下Cros策略中的预检请求是什么
预检请求除了检查ip还检查些啥(还有请求方式等)
在 CORS(跨源资源共享)策略中,预检请求(Preflight Request) 是一种特殊的 HTTP 请求,用于在实际请求之前询问服务器是否允许跨域请求。预检请求是 CORS 安全机制的一部分,主要用于处理那些可能对服务器数据产生副作用的复杂请求。
浏览器会先发送一个 OPTIONS
预检请求,询问服务器是否允许该跨域请求。
1. 为什么需要预检请求?
预检请求的主要目的是在实际发送请求之前,验证服务器是否允许该跨域请求。这是因为某些 HTTP 请求(如 POST
、PUT
、DELETE
等)可能会对服务器的数据产生修改,因此需要额外的安全检查。
预检请求的触发条件
预检请求会在以下情况下被触发:
-
请求方法不是简单请求:简单请求方法包括
GET
、HEAD
和POST
(且POST
请求的Content-Type
仅限于application/x-www-form-urlencoded
、multipart/form-data
或text/plain
)。如果请求方法是PUT
、DELETE
或其他非简单方法,或者POST
请求的Content-Type
不是上述三种之一,就会触发预检请求。 -
自定义请求头:如果请求中包含自定义的 HTTP 头(如
X-Custom-Header
),也会触发预检请求。 -
携带用户凭证:如果请求设置了
withCredentials = true
(即请求会携带 Cookie 或 HTTP 认证信息),也会触发预检请求。预检请求的流程:
-
浏览器发送
OPTIONS
请求:-
请求方法:
OPTIONS
-
请求头:
-
Origin
:指定请求的来源(如http://example.com
) -
Access-Control-Request-Method
:指定实际请求的方法(如PUT
) -
Access-Control-Request-Headers
:指定实际请求中包含的自定义头(如X-Custom-Header
)
-
-
-
服务器响应:
-
服务器需要在响应中包含以下 CORS 相关头:
-
Access-Control-Allow-Origin
:指定允许的来源(如http://example.com
或*
) -
Access-Control-Allow-Methods
:指定允许的请求方法(如GET, POST, PUT
) -
Access-Control-Allow-Headers
:指定允许的自定义头(如X-Custom-Header
) -
Access-Control-Allow-Credentials
:如果允许携带用户凭证,需设置为true
-
Access-Control-Max-Age
:可选,指定预检请求结果的有效期(单位为秒),用于缓存预检结果。
-
-
-
浏览器验证响应:
-
如果服务器的响应中包含允许的 CORS 头,浏览器会继续发送实际的请求。
-
如果服务器的响应中缺少必要的 CORS 头,浏览器会阻止实际请求的发送,并抛出跨域错误。
-
跨域里的简单请求和复杂请求
简单请求是指那些不需要发送预检请求的跨域请求。它们满足以下条件:
-
GET
-
HEAD
-
POST
复杂请求是指那些不符合简单请求条件的跨域请求。它们需要发送预检请求(Preflight Request)来验证服务器是否允许该请求。复杂请求的特征包括:
-
请求方法:使用除
GET
、HEAD
和POST
之外的其他 HTTP 方法(如PUT
、DELETE
、PATCH
等)。 -
请求头:包含自定义请求头(如
X-Custom-Header
、Authorization
等)。 -
POST
请求的Content-Type
:不是application/x-www-form-urlencoded
、multipart/form-data
或text/plain
。 -
携带用户凭证:请求设置了
withCredentials = true
,并且需要携带 Cookie 或 HTTP 认证信息。
cookie在浏览器存储时存在些什么字段(比如存用户标识存些什么属性,比如名字,过期时间之类的)
Cookie 是一种在浏览器中存储少量数据的机制,通常用于跟踪用户会话、用户偏好设置或身份验证信息。
名称(Name)
Cookie 的名称是一个字符串,用于标识该 Cookie。例如:
-
session_id
-
user_pref
-
auth_token
2. 值(Value)
Cookie 的值是与名称关联的数据,通常是一个字符串。例如:
-
session_id=abc123
-
user_pref=dark_mode
3. 过期时间(Expires/Max-Age)
Cookie 的过期时间决定了它在浏览器中存储的时长。有两种方式设置过期时间:
-
Expires
:一个具体的日期和时间,格式为 GMT 时间戳。例如:http复制
Expires=Wed, 21 Oct 2025 07:28:00 GMT
-
Max-Age
:Cookie 的有效时长,单位为秒。例如:http复制
Max-Age=3600
如果没有设置过期时间,Cookie 将被视为会话 Cookie,仅在浏览器会话期间有效,关闭浏览器后会被删除。
4. 路径(Path)
Path
字段指定了 Cookie 适用的 URL 路径。如果未指定,默认为设置 Cookie 的当前路径。例如:
-
Path=/
:Cookie 在整个网站的所有路径下都有效。 -
Path=/admin
:Cookie 仅在/admin
路径下有效。
5. 域(Domain)
Domain
字段指定了 Cookie 适用的域名。如果未指定,默认为设置 Cookie 的当前域名。例如:
-
Domain=example.com
:Cookie 在example.com
及其所有子域名下有效。 -
Domain=api.example.com
:Cookie 仅在api.example.com
下有效。
6. 安全标志(Secure)
Secure
标志指示 Cookie 只能通过 HTTPS 协议发送到服务器,不能通过 HTTP 发送。这可以防止 Cookie 在不安全的网络中被窃取。例如:
http复制
Secure
7. HttpOnly 标志
HttpOnly
标志指示 Cookie 不能被 JavaScript 访问,只能通过 HTTP/HTTPS 请求发送到服务器。这可以防止 XSS 攻击通过 JavaScript 窃取 Cookie。例如:
http复制
HttpOnly
8. SameSite 属性
SameSite
属性用于控制 Cookie 在跨站请求中的行为,以防止 CSRF(跨站请求伪造)攻击。它有以下几种值:
-
Strict
:Cookie 仅在第一方上下文中发送,不会在跨站请求中发送。 -
Lax
:Cookie 在跨站 GET 请求中会发送,但其他类型的跨站请求(如 POST)不会发送。 -
None
:Cookie 会在所有请求中发送,但必须同时设置Secure
标志。
9. 其他字段
-
Priority
:指定 Cookie 的优先级(如Low
、Medium
、High
),用于控制浏览器对 Cookie 的存储和发送策略。 -
SameParty
:一种新的属性,用于进一步限制 Cookie 在跨站请求中的行为。
localStorage和cookie的区别
localStorage
和 Cookie
都是用于在浏览器端存储数据的技术,但它们在用途、存储方式、生命周期和安全性等方面存在显著区别。 localStorage
跟服务器无交互,Cookie
和服务器有交互。
存储位置
-
localStorage
:-
存储在浏览器的本地存储中。
-
数据仅在客户端(浏览器)中存储,不会发送到服务器。
-
-
Cookie
:-
存储在浏览器中,但每次 HTTP 请求时,浏览器会自动将相关的
Cookie
发送到服务器。 -
数据会在客户端和服务器之间传输。
-
存储容量
-
localStorage
:-
每个域名大约可以存储 5MB 数据(具体取决于浏览器)。
-
适合存储较大容量的数据。
-
-
Cookie
:-
每个
Cookie
的大小限制为 4KB 左右。 -
适合存储少量数据。
-
生命周期
-
localStorage
:-
数据是持久化的,除非手动清除(如通过代码或浏览器设置),否则数据会一直存在。
-
-
Cookie
:-
可以设置过期时间(
Expires
或Max-Age
)。 -
如果未设置过期时间,则为会话 Cookie,仅在浏览器会话期间有效,关闭浏览器后会被删除。
-
安全性
-
localStorage
:-
数据仅存储在客户端,不会发送到服务器,因此不会暴露在 HTTP 请求中。
-
但因为
localStorage
可以通过 JavaScript 访问,因此容易受到 XSS(跨站脚本攻击)的影响。
-
-
Cookie
:-
数据会随着每次 HTTP 请求发送到服务器,容易在传输过程中被窃取(除非使用 HTTPS)。
-
可以通过设置
HttpOnly
标志防止 JavaScript 访问,从而降低 XSS 攻击的风险。 -
可以通过设置
Secure
标志确保Cookie
只通过 HTTPS 发送,防止中间人攻击。
-
用途
-
localStorage
:-
用于存储不需要发送到服务器的客户端数据,例如用户偏好设置、主题模式、本地存储的表单数据等。
-
适合存储较大容量的结构化数据。
-
-
Cookie
:-
主要用于身份验证(如会话管理)、跟踪用户行为或存储少量的用户偏好设置。
-
适合存储需要在客户端和服务器之间传输的数据(如会话 ID、认证令牌等)
-
性能影响
-
localStorage
:-
数据存储在浏览器中,不会影响 HTTP 请求的大小。
-
-
Cookie
:-
每次 HTTP 请求都会携带
Cookie
数据,过多或过大的Cookie
会增加请求的大小,影响性能。
-
存储用户登录态是怎么做的
存储用户登录态是Web应用中一个重要的功能,用于在用户登录后保持其身份状态,以便在后续请求中识别用户身份。
基于Cookie和Session的登录态管理
工作原理:
-
用户输入登录凭据(如用户名和密码)并提交登录请求。
-
服务器验证用户信息,若合法,则生成一个唯一的 Session ID,并将用户信息与该 Session ID 关联存储在服务器端。
-
服务器通过
Set-Cookie
响应头将 Session ID 发送给客户端,客户端将其存储在Cookie中。 -
客户端在后续请求中自动携带该Cookie,服务器通过 Session ID 查找对应的用户信息,从而识别用户身份。
基于Token的登录态管理(如JWT)
工作原理:
-
用户登录成功后,服务器生成一个 Token(如JWT),其中包含用户的身份信息和签名。
-
服务器将 Token 发送给客户端,客户端通常将其存储在
localStorage
、sessionStorage
或Cookie
中。 -
客户端在后续请求中将 Token 放在HTTP请求头中(如
Authorization
字段),服务器通过验证 Token 的签名来确认用户身份。
OAuth2.0和OpenID Connect:
-
利用第三方服务(如Google、GitHub)进行用户认证,返回的Token用于后续请求。
-
优点是安全性高,缺点是依赖第三方服务,生命周期由第三方控制
CSS:
全屏浮层弹窗,要求弹窗水平垂直居中,如何做
使用 Flexbox 或 CSS Grid,因为它们简单且现代,兼容性良好。
display: flex; /* 使用 Flexbox 布局 */
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
z-index: 1000; /* 确保浮层在最上层 */
display: grid; /* 使用 Grid 布局 */
place-items: center; /* 水平和垂直居中 */
z-index: 1000; /* 确保浮层在最上层 */
是否使用过element组件库之类的,组件库中的弹窗触发条件的实现原理是什么
在使用 Element UI 组件库时,弹窗的触发条件通常是通过控制弹窗组件的 visible
属性来实现的。
-
visible
属性是一个布尔值,当设置为true
时,弹窗显示;设置为false
时,弹窗隐藏。 -
通常通过用户操作(如点击按钮)触发方法来改变
visible
属性的值。
纯文本行内垂直居中如何做(行高line-height)
实现纯文本的行内垂直居中可以通过设置line-height
属性来完成。这种方法适用于单行文本
.container {
width: 300px; /* 容器宽度 */
height: 100px; /* 容器高度 */
background-color: #f0f0f0; /* 背景颜色 */
text-align: center; /* 水平居中 */
}
.text {
line-height: 100px; /* 行高等于容器高度 */
font-size: 16px; /* 字体大小 */
}
oss项目文件传输的大文件切片怎么实现的
在实现大文件切片上传时,通常会将文件分割成多个小片段(分片),然后并行上传这些分片,最后在服务器端将分片拼接成完整的文件。
1. 文件切片
将大文件分割成多个小片段,每个片段具有固定的大小。例如,一个100MB的文件可以被分割成10个10MB的分片。
2. 并行上传
将分片并行上传到服务器。每个分片可以独立发送,这样可以充分利用网络带宽,提高上传速度。
3. 分片信息管理
每个分片在上传时需要携带额外的信息,例如:
-
分片序号:用于标识分片的顺序。
-
文件总分片数:用于在服务器端拼接文件时确认所有分片已上传完成。
-
文件哈希值:用于校验文件的完整性。
4. 服务器端处理
服务器接收到所有分片后,根据分片序号将它们拼接成完整的文件,并进行完整性校验。
5. 重试机制
如果某个分片上传失败,客户端会自动重试上传该分片,直到成功。
6. 并发控制
为了优化性能,可以设置最大并发数,避免过多的并发请求对服务器造成压力。
7. 进度管理
通过记录每个分片的上传状态,可以实时更新上传进度,并在所有分片上传完成后通知用户。
是否了解es6新增的fetch请求
fetch
是 ES6 中引入的一个用于发起网络请求的 API,它提供了一种更简洁、更现代的方式来替代传统的 XMLHttpRequest
。fetch
基于 Promise 实现,支持异步操作,使得网络请求的代码更加简洁和易于管理。
发起 GET 请求
fetch('https://api.example.com/data')
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json(); // 解析 JSON 数据
})
.then(data => {
console.log(data); // 处理返回的数据
})
.catch(error => {
console.error('There was a problem with the fetch operation:', error);
});
发起 POST 请求
fetch('https://api.example.com/data', {
method: 'POST', // 请求方法
headers: {
'Content-Type': 'application/json' // 设置请求头
},
body: JSON.stringify({ key: 'value' }) // 请求体
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
rem的原理
rem
是一种相对单位,用于 CSS 中的布局和样式设计。
响应式设计:
-
rem
单位使得布局可以根据根元素的字体大小动态调整,非常适合响应式设计。例如,可以通过媒体查询调整根元素的字体大小,从而实现不同屏幕尺寸下的布局调整。
-
易于维护:
-
使用
rem
单位时,只需要调整根元素的字体大小,即可全局影响所有使用rem
的样式,而不需要逐个修改样式规则。
-
-
可伸缩性:
-
rem
单位使得设计更具可伸缩性,适合现代 Web 设计中对灵活性的要求。
-
-
无障碍性:
-
用户可以通过浏览器设置调整根元素的字体大小,而使用
rem
的样式会自动适应这些调整,从而提高无障碍性。
-
图片懒加载怎么做的
图片懒加载是一种常见的前端优化技术,用于延迟加载页面上的图片,直到用户滚动到图片所在位置时才加载。这种技术可以显著减少页面加载时间,节省带宽,提升用户体验,尤其适用于图片较多的页面或移动设备。
-
将图片的真实地址存储在自定义属性(如
data-src
)中,而不是直接放在src
属性中。 -
监听滚动事件,当图片进入可视区域时,将
data-src
的值赋给src
,从而触发图片加载。
使用第三方库(如 lozad.js
)
lozad.js
是一个轻量级的图片懒加载库,基于 Intersection Observer
API 实现,使用简单,兼容性好。
使用 HTML 的 loading="lazy"
属性(原生懒加载)
从 Chrome 76 开始,HTML 支持原生懒加载,通过在 <img>
标签中添加 loading="lazy"
属性即可实现。
滚动条套滚动条时怎么判断元素是否在视口内
-
如果只需要判断元素是否在全局视口中,可以直接使用
Element.getBoundingClientRect()
。 -
如果需要考虑嵌套滚动容器,可以通过计算元素和容器的边界来判断。
-
使用
Intersection Observer
API 是最推荐的方式,因为它性能优越,且可以自动处理嵌套滚动容器的场景。
浏览器缓存怎么做的
浏览器缓存是提升Web应用性能的关键技术之一,通过将静态资源(如CSS、JavaScript、图片等)存储在浏览器本地,可以避免重复从服务器下载,显著减少页面加载时间,改善用户体验
-
缓存机制概述
-
浏览器缓存将用户访问过的网页资源存储在本地设备上。当用户再次访问同一网站时,浏览器会优先从本地缓存中加载这些资源,而不是重新从服务器下载。
-
-
缓存的存储层级
-
内存缓存(Memory Cache):存储频繁访问的小型资源,如字体、脚本和图片。关闭浏览器后数据会被清除。
-
硬盘缓存(Disk Cache):存储大文件,如视频和大型图片。即使关闭浏览器,数据仍然保留。
-
磁盘缓存(Disk-based Cache):存储长期使用的静态资源,如HTML页面和CSS文件。关闭浏览器后数据依然存在。
-
-
缓存状态与验证机制
-
浏览器缓存的状态分为三种:未缓存(Uncached)、有效(Valid)和无效(Stale)。验证机制通过HTTP头部中的
ETag
和Last-Modified
字段来判断资源是否发生变化。
-
-
缓存控制策略
-
强缓存(Strong Cache):通过
Expires
字段控制,资源在指定时间后过期,浏览器不会再次向服务器验证。 -
协商缓存(Conditional Cache):通过
Cache-Control
字段控制,浏览器会向服务器发送请求头中的If-None-Match
或If-Modified-Since
字段来验证资源是否已更新。
-
希望从一些数据指标去衡量页面的性能,有哪些数据口径可以去衡量
1. 响应速度指标
-
TTFB(Time to First Byte):从请求发出到接收到第一个字节的时间,反映了服务器响应的延迟。
-
页面加载时间(Load Time):页面完全加载所需的时间,包括所有资源(如图片、脚本等)的加载。
-
资源加载时间(Resource Load Time):特定资源(如图片、CSS、JavaScript等)的加载时间。
-
P90/P95/P99 延迟时间:分别表示 90%、95% 和 99% 的请求完成时间,用于评估极端情况下的性能。
2. 可用性指标
-
访问成功率(Uptime):网站可用的时间比例,反映网站的稳定性。
-
服务响应时间(Response Time):服务器处理请求并返回响应的时间。
-
DNS 解析时间:域名解析为 IP 地址所需的时间。
3. 资源使用指标
-
页面大小(Page Size):页面及其资源的总大小,影响加载速度。
-
请求数量(Number of Requests):页面加载时发起的 HTTP 请求总数。
-
缓存利用率(Cache Hit Rate):从缓存中加载资源的比例,反映缓存策略的有效性。
4. 用户体验指标
-
首次内容绘制(First Contentful Paint, FCP):浏览器渲染页面上第一个内容的时间。
-
最大内容绘制(Largest Contentful Paint, LCP):页面上最大内容元素渲染完成的时间。
-
交互时间(Time to Interactive, TTI):页面完全加载并准备好用户交互的时间。
-
累积布局偏移(Cumulative Layout Shift, CLS):页面加载过程中布局变化的累积量。
5. 安全性指标
-
SSL 评级:网站 SSL 证书的安全等级。
-
安全漏洞数量:网站存在的安全漏洞数量。
-
防护能力:网站对攻击的防护能力。
6. 性能评分体系
-
综合得分:将响应速度、可用性、资源使用和安全性等指标加权计算得出的综合评分。
-
性能等级:根据得分划分的性能等级(如优秀、良好、一般、较差、很差)。
7. 数据采集与分析
-
监测点设置:合理分布监测点,覆盖主要用户区域和不同运营商。
-
采集频率:根据需求设置实时、常规和深度监测频率。
-
异常值处理:剔除异常数据,标记可疑数据点,补充缺失数据。
-
统计分析:计算平均值、分析趋势变化、识别异常模式。