面试笔记
1、浏览器缓存机制,强缓存与协商缓存,缓存命中。
浏览器缓存机制是提升网页性能的关键技术。它允许浏览器存储网页资源,并在后续请求中直接使用这些资源,从而减少网络延迟和服务器负载。浏览器缓存主要分为两种类型:强缓存和协商缓存。
1. 浏览器缓存机制
当浏览器请求一个资源时,会先检查本地缓存。如果缓存命中,则直接使用缓存的资源;否则,浏览器会向服务器发送请求,获取最新的资源。
2. 缓存命中
缓存命中是指浏览器在本地缓存中找到了请求的资源,并直接使用该资源。缓存命中可以显著提升网页加载速度,减少网络流量。
3. 强缓存
- 定义:
- 强缓存是指浏览器在不向服务器发送请求的情况下,直接使用本地缓存的资源。
- 强缓存通过
Expires
或Cache-Control
HTTP 头部来实现。
- Expires:
Expires
指定了缓存资源的过期时间,是一个绝对时间。- 如果当前时间早于
Expires
指定的时间,则浏览器直接使用缓存的资源。 Expires
的缺点是依赖于客户端的时间,如果客户端时间不准确,可能会导致缓存失效。
- Cache-Control:
Cache-Control
是一个相对时间,它指定了缓存资源的最大有效时间。- 常用的
Cache-Control
指令包括:max-age
:指定缓存资源的最大有效时间,单位为秒。no-cache
:可以缓存在客户端,但每次都必须去服务器检查新鲜度,来决定从服务器获取最新资源。no-store
:不允许在客户端存储,每次都要从服务器请求新的资源。private
:缓存只能被单个用户缓存,不能作为共享缓存(即代理服务器不可缓存)。public
:可以被所有的用户缓存,包括终端用户和代理服务器。
Cache-Control
的优先级高于Expires
。
4. 协商缓存
- 定义:
- 协商缓存是指浏览器向服务器发送请求,询问服务器缓存资源是否过期。
- 如果缓存资源未过期,服务器返回 304 Not Modified,浏览器直接使用本地缓存的资源。
- 如果缓存资源已过期,服务器返回 200 OK,并返回最新的资源。
- Last-Modified/If-Modified-Since:
Last-Modified
是服务器返回的 HTTP 头部,表示资源的最后修改时间。If-Modified-Since
是浏览器发送的 HTTP 头部,表示浏览器缓存的资源的最后修改时间。- 当浏览器请求资源时,会发送
If-Modified-Since
头部,值为缓存资源的Last-Modified
值。 - 服务器比较
If-Modified-Since
和资源的最后修改时间,如果相同,则返回 304 Not Modified;否则,返回 200 OK 和最新的资源。
- Etag/If-None-Match:
Etag
是服务器返回的 HTTP 头部,表示资源的唯一标识。If-None-Match
是浏览器发送的 HTTP 头部,表示浏览器缓存的资源的Etag
值。- 当浏览器请求资源时,会发送
If-None-Match
头部,值为缓存资源的Etag
值。 - 服务器比较
If-None-Match
和资源的Etag
值,如果相同,则返回 304 Not Modified;否则,返回 200 OK 和最新的资源。 Etag
的优先级高于Last-Modified
。
总结
- 强缓存优先于协商缓存。
- 当强缓存命中时,浏览器直接使用缓存的资源,不向服务器发送请求。
- 当强缓存失效时,浏览器会向服务器发送请求,询问缓存资源是否过期。
- 如果缓存资源未过期,服务器返回 304 Not Modified,浏览器直接使用缓存的资源。
- 如果缓存资源已过期,服务器返回 200 OK,并返回最新的资源。
希望这些信息能够帮助你理解浏览器的缓存机制。
2、防抖和节流简述实现
防抖(Debounce)和节流(Throttle)是前端开发中常用的性能优化技术,用于限制事件处理函数的执行频率,从而提高页面性能和用户体验。
防抖(Debounce)
- 定义:
- 防抖是指在事件被触发后,延迟一段时间再执行回调函数。
- 如果在延迟时间内再次触发事件,则重新计时。
- 只有当事件停止触发一段时间后,回调函数才会执行。
- 应用场景:
- 搜索框输入:在用户输入停止一段时间后,再发送搜索请求。
- 窗口大小调整:在窗口调整完成后,再重新计算页面布局。
- 按钮点击:防止用户快速重复点击按钮。
- 实现:
|
|
节流(Throttle)
- 定义:
- 节流是指在一段时间内,只执行一次回调函数。
- 如果在该时间内再次触发事件,则忽略该事件。
- 确保回调函数在一段时间内最多执行一次。
- 应用场景:
- 滚动事件:在用户滚动页面时,每隔一段时间执行一次回调函数,例如加载更多内容。
- 鼠标移动事件:在用户移动鼠标时,每隔一段时间执行一次回调函数,例如更新鼠标位置。
- 高频点击:用户快速点击的时候,限制一段时间只执行一次。
- 实现:
|
|
总结
- 防抖:将多次高频操作优化为只执行一次。
- 节流:将多次高频操作优化为每隔一段时间执行一次。
在实际开发中,应根据具体场景选择合适的优化方式。
3、跨域是什么?解决方式 jsonp、cors、反向代理
跨域是指浏览器的一种安全机制,它限制了网页从一个源(协议、域名、端口)向另一个源发送请求。以下是对跨域的详细解释以及常见的解决方案:
1. 跨域的定义和原因:
- 同源策略:
- 浏览器出于安全考虑,实施了同源策略(Same-Origin Policy)。
- 同源策略规定,只有当协议、域名和端口都相同时,两个 URL 才被认为是同源的。
- 例如:
http://www.example.com/page1
和http://www.example.com/page2
是同源的。http://www.example.com/page1
和https://www.example.com/page1
不是同源的(协议不同)。http://www.example.com/page1
和http://sub.example.com/page1
不是同源的(域名不同)。http://www.example.com:8080/page1
和http://www.example.com:8081/page1
不是同源的(端口不同)。
- 跨域限制:
- 当网页试图从一个与当前源不同的源请求资源时,浏览器会阻止该请求,这就是跨域限制。
- 跨域限制旨在防止恶意网站窃取用户的敏感信息。
2. 常见的跨域解决方案:
- JSONP(JSON with Padding):
- 原理:利用
<script>
标签的跨域特性,通过动态创建<script>
标签来发送请求。 - 优点:兼容性好,支持所有浏览器。
- 缺点:只支持 GET 请求,安全性较低。
- 使用方法:通过script标签的src属性,发送带有callback参数的GET请求,服务端再将接口返回数据拼凑到callback函数中,返回给浏览器。 之后浏览器解析执行,从而前端拿到callback函数返回的数据。
- 原理:利用
- CORS(跨域资源共享):
- 原理:通过在服务器端设置 HTTP 头部,允许浏览器跨域请求。
- 优点:支持各种 HTTP 请求方法,安全性高。
- 缺点:需要浏览器和服务器都支持。
- 使用方法:服务器端设置
Access-Control-Allow-Origin
等 HTTP 头部,指定允许跨域的源。
- 反向代理:
- 原理:在服务器端设置一个代理服务器,将跨域请求转发到目标服务器,然后将响应返回给客户端。
- 优点:可以解决所有跨域问题,无需修改客户端代码。
- 缺点:需要配置服务器。
- 使用方法:通过 Nginx、Apache 等 Web 服务器配置反向代理,将客户端请求转发到目标服务器。
3. 总结:
- JSONP 适用于简单的 GET 请求,但存在安全风险。
- CORS 是现代 Web 开发中最常用的跨域解决方案,具有良好的安全性和灵活性。
- 反向代理是一种通用的跨域解决方案,适用于各种复杂的场景。
在实际开发中,应根据具体情况选择合适的跨域解决方案。
4、如何防范XSS和CSRF攻击
为了有效防御 XSS(跨站脚本攻击)和 CSRF(跨站请求伪造)这两种常见的网络攻击,我们需要采取一系列综合性的安全措施。以下是对这两种攻击的防御方法:
XSS 攻击的防御:
- 输入验证和过滤:
- 对所有用户输入的数据进行严格的验证和过滤,确保输入的数据符合预期的格式和类型。
- 使用白名单机制,只允许特定的字符和标签,拒绝其他所有输入。
- 对特殊字符进行转义,例如将
<
转义为<
,将>
转义为>
。
- 输出编码:
- 在将用户输入的数据输出到网页时,进行正确的编码,防止浏览器将其解析为可执行的脚本。
- 使用 HTML 编码、JavaScript 编码或 URL 编码,根据输出的上下文选择合适的编码方式。
- 内容安全策略(CSP):
- 使用 HTTP 头部
Content-Security-Policy
,限制浏览器可以加载的资源来源。 - 设置白名单,只允许加载来自受信任的域名或来源的脚本、样式表、图片等资源。
- 禁用
eval()
等危险的 JavaScript 函数。
- 使用 HTTP 头部
- 使用 httpOnly Cookie:
- 设置 Cookie 的
HttpOnly
属性,防止 JavaScript 代码访问 Cookie,从而避免 Cookie 被窃取。
- 设置 Cookie 的
- 使用安全的框架和库:
- 使用经过安全审计的框架和库,避免使用存在已知漏洞的组件。
- 保持使用的框架和库为最新版本,及时修复安全漏洞。
CSRF 攻击的防御:
- 使用 CSRF Token:
- 在用户请求中添加一个随机的、不可预测的 Token,服务器端验证 Token 的有效性。
- Token 可以存储在 Session 或 Cookie 中,并在每次请求时进行验证。
- 确保 Token 的随机性和唯一性,防止攻击者预测或伪造 Token。
- 验证 HTTP Referer:
- 检查 HTTP 请求的 Referer 头部,验证请求是否来自受信任的来源。
- 这种方法并非绝对可靠,因为 Referer 头部可以被伪造,但可以作为一种辅助手段。
- 使用 SameSite Cookie:
- 设置 Cookie 的
SameSite
属性,限制 Cookie 只能在同源请求中发送。 SameSite
属性有三个值:Strict
、Lax
和None
,根据实际情况选择合适的属性值。
- 设置 Cookie 的
- 验证码:
- 在一些敏感操作中,比如转账,修改密码等,增加验证码,可以有效的防止CSRF。
- 避免使用 GET 请求执行敏感操作:
- 敏感操作应该使用 POST、PUT 或 DELETE 等 HTTP 方法,避免使用 GET 请求。
综合防御:
- 同时采取 XSS 和 CSRF 的防御措施,形成多层次的安全防护体系。
- 定期进行安全审计和漏洞扫描,及时发现和修复安全漏洞。
- 加强用户安全意识教育,提醒用户注意网络安全风险。
通过采取这些综合性的防御措施,可以有效地降低 XSS 和 CSRF 攻击的风险,保护网站和用户的安全。
5、浏览器http请求服务器接口数据的五种方式
浏览器向服务器接口请求数据主要有以下五种方式:
-
XMLHttpRequest (XHR):
- 这是最传统的浏览器 API,允许 JavaScript 发送 HTTP 请求。
- 它支持各种 HTTP 方法(GET、POST、PUT、DELETE 等)。
- 可以处理不同类型的数据(XML、JSON、文本等)。
- 使用步骤:
- 创建 XMLHttpRequest 对象。
- 初始化请求(open 方法)。
- 发送请求(send 方法)。
- 处理响应(onreadystatechange 事件)。
- 优点:兼容性好,支持各种 HTTP 方法和数据类型。
- 缺点:语法相对复杂,编写和维护较为繁琐。
-
Fetch API:
- 这是一个较新的浏览器 API,提供了更强大和灵活的 HTTP 请求方式。
- 基于 Promise,使异步操作更加简洁。
- 支持流式处理,可以高效地处理大型数据。
- 优点:语法简洁,基于 Promise,支持流式处理。
- 缺点:兼容性相对较差(旧版本浏览器不支持)。
-
jQuery AJAX:
- jQuery 库提供的 AJAX 方法,简化了 XMLHttpRequest 的使用。
- 提供了多种 AJAX 相关的方法,如
$.ajax()
、$.get()
、$.post()
等。 - 可以处理不同类型的数据(JSON、XML、HTML 等)。
- 优点:简化了 AJAX 操作,兼容性好。
- 缺点:依赖 jQuery 库,增加了页面体积。
-
Axios:
- 一个流行的基于 Promise 的 HTTP 客户端,可以在浏览器和 Node.js 中使用。
- 提供了丰富的功能,如请求和响应拦截、转换请求和响应数据、取消请求等。
- 支持各种 HTTP 方法和数据类型。
- 优点:功能强大,语法简洁,支持浏览器和 Node.js。
- 缺点:需要引入第三方库。
-
WebSocket:
- 一种全双工通信协议,允许浏览器和服务器之间建立持久连接。
- 适用于需要实时数据传输的场景,如聊天应用、在线游戏等。
- 优点:实时性好,支持双向通信。
- 缺点:不适用于传统的请求-响应模式。
6、长轮询和websocket的工作原理、区别、应用场景
长轮询和 WebSocket 都是在 Web 开发中用于实现实时通信的技术,它们的工作原理、区别和应用场景如下:
1. 长轮询 (Long Polling)
- 工作原理:
- 客户端向服务器发送一个 HTTP 请求。
- 服务器收到请求后,不会立即返回响应,而是保持连接打开,直到有新的数据可用或达到预设的超时时间。
- 一旦有新数据,服务器立即返回响应,并将数据发送给客户端。
- 客户端收到响应后,立即再次发送一个新的请求,重复上述过程。
- 优点:
- 实现简单,基于标准的 HTTP 协议,兼容性好。
- 适用于对实时性要求不是特别高的场景。
- 缺点:
- 服务器需要保持大量连接,资源消耗较大。
- 存在一定的延迟,因为每次数据更新都需要重新建立连接。
- 频繁的 HTTP 请求会增加网络开销。
- 应用场景:
- 简单的聊天应用。
- 实时通知系统。
- 股票价格等数据更新频率较低的场景。
2. WebSocket
- 工作原理:
- 客户端和服务器通过一次握手建立持久的 TCP 连接。
- 连接建立后,双方可以随时双向发送数据,无需频繁建立和关闭连接。
- WebSocket 协议使用帧(frame)进行数据传输,效率更高。
- 优点:
- 实时性高,延迟低。
- 全双工通信,服务器可以主动推送数据给客户端。
- 减少了网络开销和服务器资源消耗。
- 缺点:
- 实现相对复杂,需要服务器端和客户端都支持 WebSocket 协议。
- 某些旧浏览器可能不支持。
- 某些防火墙可能需要配置以支持WebSocket。
- 应用场景:
- 实时游戏。
- 在线协作工具。
- 实时金融数据。
- 高并发的聊天应用。
3. 长轮询和 WebSocket 的区别
特性 | 长轮询 (Long Polling) | WebSocket |
---|---|---|
通信方式 | 半双工 | 全双工 |
连接状态 | 短连接 | 长连接 |
实时性 | 较低 | 较高 |
服务器资源 | 消耗较高 | 消耗较低 |
实现难度 | 简单 | 复杂 |
兼容性 | 较好 | 相对较差 |
4. 应用场景的选择
- 如果对实时性要求不高,且需要兼容旧浏览器,可以选择长轮询。
- 如果对实时性要求高,且需要服务器主动推送数据,可以选择 WebSocket。
- 如果用户所处的环境带宽较低或网络提供商不稳定,长轮询的架构可以重新建立连接,而不会带来额外的麻烦。
总而言之,长轮询和 WebSocket 都是实现实时通信的有效技术,选择哪种技术取决于具体的应用场景和需求。
7、tcp拥塞控制的概念原理,拥塞控制的几种方式
TCP拥塞控制是传输控制协议(TCP)中用于避免网络拥塞的一系列机制。当网络中传输的数据量超过网络设备的承载能力时,就会发生拥塞,导致数据包丢失、延迟增加等问题。TCP拥塞控制旨在通过调整发送方的发送速率,使网络流量与网络容量相匹配,从而提高网络的整体性能。
1. 拥塞控制的概念和原理
- 概念:
- TCP拥塞控制的目标是防止过多的数据注入到网络中,避免网络出现过载的情况。
- 它是一种全局性的控制机制,涉及到发送方、接收方以及网络中的路由器等多个环节。
- 原理:
- TCP通过维护一个“拥塞窗口”(cwnd)来控制发送方的发送速率。
- 拥塞窗口的大小反映了网络当前的拥塞程度。
- TCP会根据网络的拥塞情况动态调整拥塞窗口的大小,从而实现拥塞控制。
- TCP拥塞控制的核心思想是:
- 在网络状况良好的情况下,逐渐增加发送速率,充分利用网络资源。
- 在检测到网络拥塞时,迅速降低发送速率,缓解拥塞状况。
2. 拥塞控制的几种方式
TCP拥塞控制主要包括以下几种算法:
- 慢启动(Slow Start):
- 在连接建立初期或超时重传后,将拥塞窗口设置为一个较小的值(通常为1个MSS,即最大报文段长度)。
- 每收到一个ACK确认报文,拥塞窗口的大小就翻倍。
- 慢启动的目的是快速找到网络的可用带宽。
- 拥塞避免(Congestion Avoidance):
- 当拥塞窗口达到慢启动阈值(ssthresh)时,进入拥塞避免阶段。
- 每收到一个ACK确认报文,拥塞窗口的大小只增加1个MSS。
- 拥塞避免的目的是防止拥塞窗口增长过快,避免网络出现拥塞。
- 快重传(Fast Retransmit):
- 当发送方收到三个重复的ACK确认报文时,认为某个数据包丢失,立即重传该数据包,而无需等待超时。
- 快重传可以提高数据包的重传效率,减少延迟。
- 快恢复(Fast Recovery):
- 当发生快重传时,进入快恢复阶段。
- 将拥塞窗口的大小设置为当前窗口的一半,然后执行拥塞避免算法。
- 快恢复的目的是尽快恢复数据传输,避免网络出现严重的拥塞。
总结
TCP拥塞控制是保证网络稳定性和可靠性的重要机制。通过慢启动、拥塞避免、快重传和快恢复等算法,TCP能够有效地控制网络拥塞,提高网络性能。
ecmascript从2015到2024的更新
ECMAScript(简称ES)自2015年(ES6/ES2015)以来,每年都会发布新版本,引入许多新特性和改进。以下是ES2015到ES2024的主要更新内容:
ES2015 (ES6)
- 类 (Classes):引入了基于原型的面向对象编程的语法糖。
- 箭头函数 (Arrow Functions):更简洁的函数语法,以及词法作用域。
- 模板字符串 (Template Literals):支持字符串插值和多行字符串。
- 解构赋值 (Destructuring):方便地从数组和对象中提取值。
- 默认参数和剩余参数 (Default and Rest Parameters):更灵活的函数参数处理。
let
和const
:块级作用域的变量声明,以及常量声明。for...of
循环:用于遍历可迭代对象。- Promise:用于处理异步操作。
- 模块 (Modules):支持原生模块化。
- Symbol:一种新的原始数据类型,用于创建唯一标识符。
- 代理 (Proxies):用于拦截和自定义对象的操作。
- Set 和 Map:新的数据结构。
ES2016 (ES7)
Array.prototype.includes()
:用于检查数组是否包含某个元素。- 指数运算符 (Exponentiation Operator):
**
用于计算幂。
ES2017 (ES8)
async
和await
:更简洁的异步编程语法。Object.values()
和Object.entries()
:用于获取对象的键值对。- 字符串填充 (String Padding):
padStart()
和padEnd()
。 Object.getOwnPropertyDescriptors()
:用于获取对象属性的描述符。- 尾逗号 (Trailing Commas):允许在函数参数和对象字面量中使用尾逗号。
ES2018 (ES9)
- 异步迭代器 (Async Iterators):用于异步遍历可迭代对象。
- Promise.prototype.finally():Promise 无论成功或失败都会执行的回调函数。
- 剩余参数和扩展运算符 (Rest/Spread Properties):用于对象字面量。
- 正则表达式改进 (Regular Expression Improvements):命名捕获组、dotAll 模式、后行断言。
ES2019 (ES10)
Array.prototype.flat()
和flatMap()
:用于扁平化数组。String.prototype.trimStart()
和trimEnd()
:用于去除字符串开头和结尾的空格。Object.fromEntries()
:用于从键值对列表创建对象。Symbol.prototype.description
:用于获取 Symbol 的描述。try...catch
改进 (Optional Catch Binding):允许省略catch
子句的参数。Function.prototype.toString()
改进:返回精确的函数源代码。
ES2020 (ES11)
BigInt
:一种新的原始数据类型,用于表示任意精度的整数。- 动态
import()
:允许在运行时动态加载模块。 - 空值合并运算符 (Nullish Coalescing Operator):
??
用于提供默认值。 - 可选链 (Optional Chaining):
?.
用于安全地访问嵌套对象属性。 Promise.allSettled()
:返回所有 Promise 的结果,无论成功或失败。globalThis
:用于在不同环境中访问全局对象。import.meta
:用于获取模块的元数据。
ES2021 (ES12)
String.prototype.replaceAll()
:用于替换字符串中所有匹配的子字符串。Promise.any()
和AggregateError
:用于处理多个 Promise 的结果。- 逻辑赋值运算符 (Logical Assignment Operators):
||=
,&&=
,??=
。 - 数字分隔符 (Numeric Separators):
_
用于分隔数字。 WeakRef
和 Finalizers:用于管理弱引用和清理对象。
ES2022 (ES13)
- 类字段 (Class Fields):允许在类中声明实例字段。
- 静态类字段和私有类字段 (Static and Private Class Fields)。
at()
方法:用于访问数组、字符串和类型化数组的元素。Object.hasOwn()
:用于检查对象是否具有指定的自有属性。- 顶级
await
(Top-level Await):允许在模块的顶层使用await
。 - 正则表达式匹配索引 (RegExp Match Indices):
d
标志。 - 错误原因 (Error Cause):允许在创建错误时指定原因。
ES2023 (ES14)
- Array find from last:
findLast()
和findLastIndex()
从数组的末尾开始查找元素。 - Hashbang Grammar:支持在脚本顶部使用
#!
注释。 - Symbols as WeakMap keys:允许将 Symbol 用作 WeakMap 的键。
- Array copy within:
Array.prototype.with()
和TypedArray.prototype.with()
使用非破坏性方法在给定索引处返回数组的副本。
ES2024 (ES15)
- Array Grouping:
Object.groupBy()
和Map.groupBy()
方法,用于对可迭代对象中的元素进行分组。 - Promise.withResolvers:
Promise.withResolvers()
方法,用于创建带有解析和拒绝函数的 Promise。 - Well-Formed Unicode Strings:加强对格式良好的 Unicode 字符串的支持。
- Resizable ArrayBuffer and Growable SharedArrayBuffer:允许创建可调整大小的 ArrayBuffer 和可增长的 SharedArrayBuffer。
- RegExp v flag:正则表达式 v 标志,允许使用 Unicode 属性转义。
这些更新不断丰富了 JavaScript 的功能,提高了开发效率和代码质量。
js数组中改变原数组的方法和不改变原数组的方法
在 JavaScript 中,数组的操作可以分为两类:改变原数组和不改变原数组。理解这两类操作对于编写高效且可维护的代码至关重要。
改变原数组的方法
这些方法会直接修改原始数组。
push()
:- 在数组末尾添加一个或多个元素。
- 返回新的数组长度。
pop()
:- 移除数组末尾的最后一个元素。
- 返回被移除的元素。
shift()
:- 移除数组的第一个元素。
- 返回被移除的元素。
unshift()
:- 在数组开头添加一个或多个元素。
- 返回新的数组长度。
splice()
:- 通过删除或替换现有元素或者原地添加新的元素来修改数组。
- 这个方法很强大,可以实现数组的增删改。
sort()
:- 对数组的元素进行排序。
- 默认按照字符串 Unicode 码位排序。
reverse()
:- 颠倒数组中元素的顺序。
不改变原数组的方法
这些方法会返回一个新的数组,而不会修改原始数组。
concat()
:- 用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。
slice()
:- 返回数组的一部分浅拷贝到一个新数组对象。原始数组不会被修改。
filter()
:- 创建一个新数组,其中包含通过所提供函数实现的测试的所有元素。
map()
:- 创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。
reduce()
:- 对数组中的每个元素执行一个reducer函数(由您提供),从而将其简化为单个输出值。
toSpliced()
:toSpliced()
方法是splice()
方法的复制版本。它返回一个新数组,并在给定的索引处删除了和/或添加了元素。
toReversed()
:toReversed()
方法是reverse()
方法的复制版本。它返回一个元素顺序相反的新数组。
toSorted()
:toSorted()
方法是sort()
方法的复制版本。它返回一个元素已排序的新数组。
with()
:with()
方法是使用给定索引和值设置数组中单个元素值的复制版本。它返回一个新数组,并在给定索引处替换了指定的值。
使用建议
- 在需要保持原始数组不变的情况下,应使用不改变原数组的方法。
- 在需要直接修改原始数组以提高性能的情况下,可以使用改变原数组的方法。
- 在React或者Vue等现代前端框架中,推荐尽量使用不改变原数组的方法,这样有利于状态的管理。
希望以上信息能够帮助你更好地理解 JavaScript 数组的操作。
typeof和instanceof的异同点
typeof
和 instanceof
都是 JavaScript 中用于类型检查的操作符,但它们的工作方式和适用场景有所不同。
typeof
操作符
- 作用:
typeof
用于返回一个操作数的数据类型字符串。- 它可以用于检测 JavaScript 的原始类型(
undefined
、boolean
、number
、string
、symbol
、bigint
)和函数。
- 特点:
typeof
返回的是类型的字符串表示,而不是布尔值。typeof null
返回"object"
,这是一个历史遗留问题,需要注意。typeof
无法准确区分对象类型(例如数组、正则表达式、日期等),它们都会返回"object"
。
- 示例:
|
|
instanceof
操作符
- 作用:
instanceof
用于检测一个对象是否属于某个构造函数的实例,或者是否在其原型链上。- 它主要用于检测对象类型。
- 特点:
instanceof
返回的是布尔值。instanceof
可以准确区分对象类型,因为它会沿着原型链向上查找。instanceof
无法检测原始类型。
- 示例:
|
|
异同点总结
- 相同点:
- 两者都用于类型检查。
- 不同点:
typeof
返回类型的字符串,instanceof
返回布尔值。typeof
主要用于检测原始类型和函数,instanceof
主要用于检测对象类型。typeof
无法准确区分对象类型,instanceof
可以。typeof null
返回"object"
,instanceof
无法检测null
。
使用场景
typeof
:- 检测变量是否已定义(
typeof variable === "undefined"
)。 - 检测原始类型。
- 检测函数。
- 检测变量是否已定义(
instanceof
:- 检测对象是否属于某个构造函数的实例。
- 检测对象是否在其原型链上。
- 区分不同的对象类型。
补充说明
- 在实际开发中,可以结合使用
typeof
和instanceof
来进行更全面的类型检查。 - 对于一些特殊的对象类型,例如
null
,需要特别注意。 - 在 TypeScript 中,类型检查更加严格,可以使用类型断言等方式进行更精确的类型判断。