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

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

const queryString = '?name=zh&age=22'
const queryParams = new URLSearchParams(queryString) 
console.log(queryParams) 

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

URL

URL 接口也是和url有关的

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

const parsedUrl = new URL(window.location.href);
console.log(parsedUrl.searchParams.get("id")); 

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

  • URL.createObjectURL(file),接受一个文件类型对象,返回一个blob:预览地址。

  • URL.revokeObjectURL(url),在不需要使用预览地址的时候,可以调用该方法进行删除,释放内存。

URL 编码和解码

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

  • encodeURI() 主要用于整个URI,因为它不会对本身属于URI的特殊字符进行编码。

  • encodeURIComponent() 主要用于编码URI中某一段,因为他会对URI中任何非标准字符进行编码。协议的://也会被编码。

  • decodeURI()用于对encodeURI编码的字符解码,不会解码url中的标准字符被编码的内容。

  • decodeURIComponent()能够解码任何特殊字符的编码

    
    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`

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)。它表明你的模块在运行时需要另一个模块作为“对等”依赖关系,因为你的模块是为与之有互操作性的特定版本的那个模块而设计的。

"peerDependencies": {
  "module-name": "1.x"
}

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

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

peerDependenciesMeta

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

"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返回值

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

  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); 

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Web面试那些事儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值