牛客面经每日一总结(十一)

Vue路由中我想用前进和后退怎么实现

  • go, 正数前进,负数后退。
  • back,相当于go(-1)
  • forward,相当于go(1)

location对象有哪些部分

  • href
  • protocol,结尾有个:
  • host,会加上端口号。
  • hostname
  • port
  • pathname,开头有个/
  • search, 开头有个?
  • hash, 开头有个#
  • origin, 完整域名, 会加上端口号
  • reload(boolean), boolean为true, 清空缓存加载, boolean为false: 本地缓存加载。
  • assign(url)指定一个url覆盖该页面,保存浏览器栈中的历史记录,类似于history.pushState()。同给href赋值一样的效果。
  • replace(url)指定一个url覆盖该页面,不保存浏览器栈中的历史记录,类似于history.replaceState()
  • toString(),读取效果和href一样,但是不能修改url值。

解析search

js 复制代码
const queryString = '?name=zh&age=22'
const queryParams = new URLSearchParams(queryString) // 返回一个可迭代对象
console.log(queryParams) //{ 'name' => 'zh', 'age' => '22' }

const paramObj = Object.fromEntries(queryParams)
console.log(paramObj)

URL

URL 接口也是和url有关的,想要了解可以看mdn

也可以调用url.searchParams去获取search中的内容

js 复制代码
// https://some.site/?id=123
const parsedUrl = new URL(window.location.href);
console.log(parsedUrl.searchParams.get("id")); // "123"

他有两个静态方法,对于本地预览文件是非常有用的。

  • URL.createObjectURL(file),接受一个文件类型对象,返回一个blob:预览地址。
  • URL.revokeObjectURL(url),在不需要使用预览地址的时候,可以调用该方法进行删除,释放内存。

实现本地预览有两种方式

URL 编码和解码

该方法可以对URI(通用资源标识符)进行编码,以便发送给浏览器。有效的URI中不能包含某些特殊的字符,例如空格。则该方法用特殊的UTF-8编码替换掉这些特殊字符。

  • encodeURI() 主要用于整个URI,因为它不会对本身属于URI的特殊字符进行编码。
  • encodeURIComponent() 主要用于编码URI中某一段,因为他会对URI中任何非标准字符进行编码。协议的://也会被编码。
  • decodeURI()用于对encodeURI编码的字符解码,不会解码url中的标准字符被编码的内容。
  • decodeURIComponent()能够解码任何特殊字符的编码
js 复制代码
    // 编码
    let uri1 = 'https://www.bai du.com'
    console.log(encodeURI(uri1))
    console.log(encodeURIComponent(uri1))

    //解码
    let uri2 = 'https%3A%2F%2Fwww.bai%20du.com'
    console.log(decodeURI(uri2))
    console.log(decodeURIComponent(uri2))

一般来说,我们使用encodeURIComponent()方法更多,因为在实践中更常见的是查询字符串参数而不是对基础URI进行编码

hash模式怎么实现前进和后退

如果是vue的话,它内部的api也是支持hash模式的。如果问我原生实现,我觉得应该是将用户访问的hash保存在数组中,当想要后退和前进的时候,可以通过findIndex查找到当前hash在数组中的位置进行操作。

浏览器为什么只能建立6个连接

浏览器限制并行连接数的原因主要是出于性能和资源管理的考虑。在HTTP/1.1协议中,浏览器通常限制每个域名下的并行连接数,以避免过多的连接占用系统资源并降低性能。

  • 性能管理:每个打开的连接都需要占用系统资源,包括网络带宽、内存和CPU。如果允许大量并行连接,系统资源可能会迅速耗尽,导致性能下降。
  • 防止过度竞争:当多个连接尝试从同一域名获取资源时,会发生竞争条件。通过限制并行连接数,可以减少竞争,从而更有效地加载网页。
  • 遵守规范:HTTP/1.1规范推荐每个浏览器最多同时建立6个连接,以平衡性能和资源消耗。这个数字在不同浏览器中可能有轻微的差异,但通常是一个合理的默认值。

需要指出的是,随着HTTP/2和HTTP/3的出现,这些限制有所松动。这两个新的HTTP协议支持多路复用,允许多个请求和响应在同一个连接上并行传输,而不需要多个连接。因此,它们在提高性能和减少连接管理方面更为高效,不再需要像HTTP/1.1那样强制限制并行连接数。

一些常见但迷惑元素类型

需要注意的是,虽然有些元素符合行内块特性,但是display并不是inline-block,一些元素符合块级元素,但是display并不是block...

display: block

  • option
  • form
  • ul
  • ol
  • dd
  • dl
  • dt

display: inline-block

  • input
  • select
  • button
  • textarea

display: inline

  • img
  • vedio

伪类伪元素

伪类: 选择处于特定状态的元素。

伪元素:虚拟出一个元素,允许你对被选择元素的特定部分修改样式

如何获取伪元素,使用getComputedStyle

js 复制代码
window.getComputedStyle(element, "::after")

阻止冒泡,阻止默认行为

  • preventDefault()阻止默认行为,但是不阻止冒泡。
  • event.stopPropagation(),同一个dom元素的事件监听器添加的全部事件不会被阻止,只会阻止不同元素的。
  • event.stopImmediatePropagation()同一dom元素的事件监听器中添加的全部事件也会被阻止。 但是根据js代码执行顺序,写在前面有阻止的事件监听器的事件是不会被阻止的。
  • return false 阻止冒泡和默认行为。阻止的冒泡好像是阻止相同类型不同dom元素,不相同类型和同一个dom元素的不会被阻止。

loaded和DOMContentLoaded区别

DOMContentLoadedload 都是与页面加载和渲染相关的事件,但它们在触发时机和内容上有一些不同。

DOMContentLoaded 事件:

DOMContentLoaded 事件在文档的 HTML 和相关资源(如CSS、脚本等)都已经被下载解析完毕,但在图片和其他媒体资源加载之前触发。这意味着文档的结构(DOM)已经准备好,可以被 JavaScript 操作,但页面的所有资源(如图片)可能还在加载中。

通常,DOMContentLoaded 事件用于执行与文档结构相关的 JavaScript 操作,如添加事件处理程序、修改 DOM 元素等。这个事件的目的是在页面加载期间执行初始化脚本,而无需等待所有资源完全加载。

load 事件:

load 事件在整个页面及其所有资源(包括图片、样式表、脚本等)都已经完全加载和渲染之后触发。这意味着页面已经准备好供用户交互和浏览,所有内容都已经可见。

load 事件通常用于执行那些依赖于页面所有资源已经加载完毕的操作,如测量页面元素的尺寸、启动动画或执行需要确保所有内容已加载的功能。这通常发生在用户可以与页面进行交互之前。

DOMContentLoaded 事件在文档结构就绪后触发,而 load 事件在整个页面及其所有资源都加载完毕后触发。通常,如果你的 JavaScript 代码只需要访问和修改文档的结构,你可以使用 DOMContentLoaded 事件,因为它会更早触发,而不需要等待所有资源加载完成。如果你的代码依赖于页面上的资源,例如图片或样式表,那么你应该等待 load 事件触发。

闭包和作用域区别

作用域(Scope):

  1. 作用域定义了变量或标识符的可见性和生命周期。它确定了代码中的哪些部分可以访问特定变量。
  2. JavaScript 中有两种主要类型的作用域:全局作用域和局部作用域。全局作用域定义在整个程序中,而局部作用域通常在函数内定义。
  3. 在作用域内,内部变量可以访问外部变量,但外部变量不能直接访问内部变量。
  4. 作用域链定义了在变量查找过程中的顺序,它是由嵌套的作用域决定的。

闭包(Closure):

  1. 闭包是函数以及其周围作用域的组合。它可以在函数定义之后访问外部作用域的变量。
  2. 闭包可以捕获包含它的函数的局部变量,即使包含函数已经执行完毕,这些局部变量依然可以被闭包函数引用。
  3. 闭包通常用于创建私有变量,模拟块级作用域,以及保存函数状态。
  4. 闭包可以使函数在不同的作用域中运行,它不仅可以访问自己的作用域,还可以访问包含它的函数的作用域。

关键区别:

  • 作用域是定义变量的可见性和生命周期,它决定了哪些变量在特定作用域中可用。
  • 闭包是函数和其包围的作用域的组合,它允许函数访问包含它的作用域的变量,即使包含函数已经执行完毕。就是延长作用域生命周期。

在实际编程中,闭包常常用于处理异步操作、封装私有数据、创建工厂函数等,而作用域是 JavaScript 中变量的可见性和生命周期的基础,它们共同构建了 JavaScript 代码的结构和行为。

packages.json中peerDependencies和peerDependenciesMeta详细说明

package.json, peerDependenciespeerDependenciesMeta 是与依赖项管理相关的字段,用于描述模块间的特殊依赖关系,尤其在开发库或框架时非常有用。

peerDependencies

用于声明一组对等依赖关系(Peer Dependencies)。它表明你的模块在运行时需要另一个模块作为"对等"依赖关系,因为你的模块是为与之有互操作性的特定版本的那个模块而设计的。

json 复制代码
"peerDependencies": {
  "module-name": "1.x"
}

这里的示例说明你的模块需要与 "module-name" 的 1.x 版本兼容。它告诉使用者,如果他们安装了你的模块,也必须安装并使用特定版本的 "module-name"。一般指定版本都是模糊版本。

使用项目侧模块依赖。打包时可以部将其打包进入。

peerDependenciesMeta

提供有关对等依赖关系的额外元信息。

json 复制代码
"peerDependenciesMeta": {
  "module-name": {
    "optional": true
  }
}

在此示例中,peerDependenciesMeta 允许你提供额外的信息。例如,"optional": true 表示 module-name 是可选的对等依赖。这意味着你的模块可以与 module-name 有更松散的互操作性,而不一定需要强制依赖于特定版本。

这两个字段通常在开发复杂模块时使用,尤其当你的模块需要与其他模块特定版本保持兼容时非常有用。它们确保使用者知道他们必须安装的对等依赖,并为这些依赖提供一些额外的元信息,例如对可选依赖的处理方式。

@import导入css的缺点

@import 是一种用于在CSS中导入外部样式表的方式,但它具有一些缺点,这些缺点可能会影响性能和开发过程的效率:

  1. 性能问题

    • @import 是同步加载的,这意味着在加载主CSS文件时,会等待导入的外部CSS文件全部下载完成后再继续加载页面。这会导致页面加载速度较慢,特别是当有多个@import 嵌套时。
  2. 不适用于异步加载

    • @import 不支持异步加载,这使得难以在页面加载后动态加载CSS文件,例如通过JavaScript。这在一些情况下可能不方便,尤其是在需要按需加载CSS的单页应用程序中。
  3. 可维护性

    • 使用 @import 可能导致样式表的可维护性下降。当样式表嵌套多个@import 规则时,不容易追踪依赖关系和理解整个样式表结构,这可能使样式表变得混乱和难以管理。
  4. 浏览器兼容性

    • 一些古老的浏览器可能不支持 @import 或支持有限,这可能会导致兼容性问题。虽然现代浏览器通常支持 @import,但如果您需要支持较旧的浏览器,就需要谨慎使用。
  5. 附加HTTP请求

    • 使用 @import 会导致额外的HTTP请求,因为每个导入的外部CSS文件都需要单独的HTTP请求。这可能会导致性能瓶颈,尤其是在移动设备上或在慢速网络连接下。
  6. 顺序问题

    • @import 导入的样式表会按照它们在主样式表中的顺序被加载。这可能会导致样式层叠顺序出现问题,因为后导入的样式表可能会覆盖前导入的样式表规则。

由于上述缺点,现在通常更倾向于使用 <link> 元素来引入外部样式表,因为它们是并行加载的,对异步加载更友好,并提供更好的性能和可维护性 。如果您要使用 @import,请谨慎使用,确保仅在适当的情况下使用,以避免性能和维护问题。

sort返回值

经过排序的原始数组的引用。

js 复制代码
  const tempArray = [1, 2, 3, 4, 5];
  tempArray.unshift(6);
  tempArray.splice(1, 2);
  tempArray.pop(1);
  tempArray.slice(2);
  tempArray.concat([3, 4]);
  const result = tempArray.sort((a, b) => {
    return b - a;
  });
  result.push(5);
  result.splice(2);
  console.log(tempArray); // [6, 4]

如何让不在可视界面的元素平滑滚动到可视区域

让非可见元素平滑滚动到可见区域内

js 复制代码
 const element = document.getElementsByClassName("bottom")[0]
 element.scrollIntoView({behavior: 'smooth'})

往期文章

专栏文章

写这篇总结的时候已找到工作,感谢自己日常总结。😁

相关推荐
m0_528723816 分钟前
HTML中,title和h1标签的区别是什么?
前端·html
Dark_programmer6 分钟前
html - - - - - modal弹窗出现时,页面怎么能限制滚动
前端·html
GDAL12 分钟前
HTML Canvas clip 深入全面讲解
前端·javascript·canvas
禾苗种树13 分钟前
在 Vue 3 中使用 ECharts 制作多 Y 轴折线图时,若希望 **Y 轴颜色自动匹配折线颜色**且无需手动干预,可以通过以下步骤实现:
前端·vue.js·echarts
GISer_Jing18 分钟前
Javascript排序算法(冒泡排序、快速排序、选择排序、堆排序、插入排序、希尔排序)详解
javascript·算法·排序算法
JustHappy36 分钟前
「我们一起做组件库🌻」做个面包屑🥖,Vue的依赖注入实战💉(VersakitUI开发实录)
前端·javascript·github
拉不动的猪1 小时前
刷刷题16
前端·javascript·面试
kiramario1 小时前
【结束】JS如何不通过input的onInputFileChange使用本地mp4文件并播放,nextjs下放入public文件的视频用video标签无法打开
开发语言·javascript·音视频
哑巴语天雨1 小时前
前端面试-网络协议篇
websocket·网络协议·http·面试·https
01_2 小时前
力扣hot100——LRU缓存(面试高频考题)
leetcode·缓存·面试·lru