likes
comments
collection
share

面试题:我一定拿下——求求收下我吧(细🐕来了,2w字,wow~)

作者站长头像
站长
· 阅读数 33

前言

最近积累了3家公司的面试,想着与其存在草稿箱里发霉,还不如放它出来为大家发光发热,共同进步。

杭州(170-220 / 天)

该家面试题给我极大的不适应感,问得面试题不是寻常的那些八股,而是对那些元素的属性等进行了一些过于偏得问题询问,出其不意,乱拳打死老师傅,不按常理出牌。

1.(场景题)如何实现一个点击回到顶部的功能

  1. 使用JavaScript和window.scrollTo()方法:
document.getElementById('backToTopBtn').addEventListener('click', function() {
  window.scrollTo({
    top: 0,
    behavior: 'smooth'
  });
});
  1. HTML中使用锚点(anchor)实现页面内的跳转。通过在链接的href属性中指定锚点的名称,点击该链接时浏览器会滚动到具有相应锚点名称的位置。
<a href="#top" id="backToTopBtn">回到顶部</a>
<div id="top"></div>

2. input上传文件的时候,可以同时选择多个文件吗?

HTML中的<input>标签的type属性设置为file时,可以同时选择多个文件进行上传。

可以通过在<input>标签上添加multiple属性来启用多文件选择功能。例如:

<input type="file" multiple>

multiple属性存在时,用户可以按住Ctrl(Windows)或Command(Mac)键并单击文件,或者使用拖放操作,选择多个文件进行上传

3. script标签能否自闭合

在HTML中,<script>标签通常不是自闭合的,因为它们可以包含内联的脚本代码或引用外部脚本文件。 传统的写法是不自闭合的:

<script src="script.js"></script>

然而,根据HTML5规范,<script>标签可以被自闭合。这意味着你可以在标签中使用自闭合的斜杠(/>),特别是当你只在其中引用外部脚本文件时:

<script src="script.js" />

需要注意的是,自闭合的<script>标签在一些旧版本的浏览器中可能不被支持,因此为了更好的兼容性,仍然建议使用传统的非自闭合写法。

4. 在页面导入样式的时候,使用link导入和使用@import导入有什么区别吗?

在页面导入样式时,使用<link>标签和@import规则都可以用来导入外部样式表,但它们之间存在一些区别。

  1. 加载顺序: <link>标签会在页面加载时同时下载和加载外部样式表,而@import规则会在页面加载完毕后再下载和加载样式表。这意味着使用<link>标签可以更快地加载样式,并且样式表的加载不会阻塞页面的渲染。
  2. 兼容性: <link>标签是HTML标签,所以它的支持性非常广泛,适用于所有主流的现代浏览器。而@import规则是CSS提供的一种导入样式表的方式,虽然也被大多数浏览器支持,但在一些旧版本的浏览器中可能存在兼容性问题。
  3. 权重: 样式表的权重也会有所不同。使用<link>标签导入的样式表具有比@import规则导入的样式表更高的权重。这意味着如果同一个样式属性在两个导入的样式表中有不同的设置,使用<link>标签导入的样式会覆盖@import规则导入的样式。
  4. 使用限制: @import规则只能在CSS样式表中使用,而不能在HTML文件中使用。<link>标签可以用于在HTML文件中导入样式表,还可以用于导入其他类型的文件,如图标文件。

5. link和@import两者的权重哪个更高

当页面同时使用<link>标签和@import规则导入相同的样式表时,<link>标签的权重会高于@import规则的权重。这意味着通过<link>标签导入的样式表将覆盖通过@import规则导入的样式表中的相同样式规则。

这是因为<link>标签是HTML标准的一部分,而@import规则是CSS规范中的一项。根据CSS规范的级联规则,来自外部样式表的规则会优先于来自嵌入样式的规则。

同时,还需要注意导入顺序的影响。如果通过<link>标签先导入样式表A,然后通过@import规则导入样式表B,样式表A中的规则将优先于样式表B中的规则。

6. title和alt属性有什么作用

title 属性是元素的提示性文本,当鼠标悬停在元素上时以工具提示的形式显示。它提供了额外的信息或解释元素内容,对于用户交互和辅助无障碍访问非常有用。

alt 属性是图像元素的替代文本,当图像无法加载时,它将代替图像显示在网页上。它对于视觉障碍用户、图像加载失败时以及搜索引擎优化很重要。

7. 简单描述一下,从网址里输入地址到页面显示的过程

  • 首先在浏览器中输入URL

  • 查找缓存:浏览器先查看浏览器缓存-系统缓存-路由缓存中是否有该地址页面,如果有则显示页面内容。如果没有则进行下一步。

    • 浏览器缓存:浏览器会记录DNS一段时间,因此,只是第一个地方解析DNS请求;
    • 操作系统缓存:如果在浏览器缓存中不包含这个记录,则会使系统调用操作系统, 获取操作系统的记录(保存最近的DNS查询缓存);
    • 路由器缓存:如果上述两个步骤均不能成功获取DNS记录,继续搜索路由器缓存;
    • ISP缓存:若上述均失败,继续向ISP搜索。
  • DNS域名解析:浏览器向DNS服务器发起请求,解析该URL中的域名对应的IP地址,然后返回给浏览器

  • 建立TCP连接:解析出IP地址后,浏览器根据IP地址和默认80端口,和目标服务器建立TCP连接

  • 发起HTTP请求:浏览器发起读取文件的HTTP请求,通过TCP三次握手把数据发送给服务器

  • 服务器响应请求并返回结果:服务器对浏览器请求做出响应,并把对应的html文件发送给浏览器

  • 关闭TCP连接:通过四次挥手释放TCP连接

  • 浏览器渲染:客户端(浏览器)解析HTML内容并渲染出来,浏览器接收到数据包后的解析流程为:

    • 构建DOM树:词法分析然后解析成DOM树(dom tree),是由dom元素及属性节点组成,树的根是document对象
    • 构建CSS规则树:生成CSS规则树(CSS Rule Tree)
    • 构建render树:Web浏览器将DOM和CSSOM结合,并构建出渲染树(render tree)
    • 布局(Layout):计算出每个节点在屏幕中的位置
    • 绘制(Painting):即遍历render树,并使用UI后端层绘制每个节点。

8. display有哪些常见的取值

在CSS中,display 属性用于控制元素的显示类型。它有多种常见的取值,包括:

  1. block: 元素将作为块级元素显示,会在父容器中占据整个可用宽度,并在下一行开始显示。
  2. inline: 元素将作为内联元素显示,只占据其内容所需的宽度,并不强制换行。
  3. inline-block: 元素会作为内联元素显示,但具有块级元素的特性,可以设置宽度和高度,并在同一行内显示多个元素。
  4. none: 元素将被隐藏,不占据任何空间,即完全隐藏该元素。
  5. flex: 元素将作为弹性容器显示,可以通过设置弹性属性来控制其子元素的排列方式。
  6. grid: 元素将作为网格容器显示,可以通过设置网格属性来控制其子元素的布局方式。
  7. table: 元素将作为表格显示,具有表格元素的特性,例如,可以设置单元格宽度、行高等。

9. 在VUE中常见的修饰符有哪些?

vue中修饰符分为以下五种:

  • 表单修饰符
  • 事件修饰符
  • 键值修饰符

表单修饰符

在我们填写表单的时候用得最多的是input标签,指令用得最多的是v-model

关于表单的修饰符有如下:

  • lazy
  • trim
  • number

lazy

在我们填完信息,光标离开标签的时候,才会将值赋予给value,也就是在change事件之后再进行信息同步

<input type="text" v-model.lazy="value">
<p>{{value}}</p>

trim

自动过滤用户输入的首空格字符,而中间的空格不会过滤

<input type="text" v-model.trim="value">

number

自动将用户的输入值转为数值类型,但如果这个值无法被parseFloat解析,则会返回原来的值

<input v-model.number="age" type="number">

事件修饰符

事件修饰符是对事件捕获以及目标进行了处理,有如下修饰符:

  • stop
  • prevent
  • self
  • once
  • capture
  • passive
  • native

stop

阻止了事件冒泡,相当于调用了event.stopPropagation方法

<div @click="shout(2)">
  <button @click.stop="shout(1)">ok</button>
</div>
//只输出1

prevent

阻止了事件的默认行为,相当于调用了event.preventDefault方法

<form v-on:submit.prevent="onSubmit"></form>

self

只当在 event.target 是当前元素自身时触发处理函数

<div v-on:click.self="doThat">...</div>

使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用 v-on:click.prevent.self 会阻止所有的点击,而 v-on:click.self.prevent 只会阻止对元素自身的点击

once

绑定了事件以后只能触发一次,第二次就不会触发

<button @click.once="shout(1)">ok</button>

capture

使事件触发从包含这个元素的顶层开始往下触发

<div @click.capture="shout(1)">
    obj1
    <div @click.capture="shout(2)">
        obj2
        <div @click="shout(3)">
            obj3
            <div @click="shout(4)">
                obj4
            </div>
        </div>
    </div>
</div>
// 输出结构: 1 2 4 3 

passive

在移动端,当我们在监听元素滚动事件的时候,会一直触发onscroll事件会让我们的网页变卡,因此我们使用这个修饰符的时候,相当于给onscroll事件整了一个.lazy修饰符

<!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发 -->
<!-- 而不会等待 `onScroll` 完成  -->
<!-- 这其中包含 `event.preventDefault()` 的情况 -->
<div v-on:scroll.passive="onScroll">...</div>

不要把 .passive 和 .prevent 一起使用,因为 .prevent 将会被忽略,同时浏览器可能会向你展示一个警告。

passive 会告诉浏览器你不想阻止事件的默认行为

native

让组件变成像html内置标签那样监听根元素的原生事件,否则组件上使用 v-on 只会监听自定义事件

<my-component v-on:click.native="doSomething"></my-component>

使用.native修饰符来操作普通HTML标签是会令事件失效的

键盘修饰符

键盘修饰符是用来修饰键盘事件(onkeyuponkeydown)的,有如下:

keyCode存在很多,但vue为我们提供了别名,分为以下两种:

  • 普通键(enter、tab、delete、space、esc、up...)
  • 系统修饰键(ctrl、alt、meta、shift...)
// 只有按键为keyCode的时候才触发
<input type="text" @keyup.keyCode="shout()">

还可以通过以下方式自定义一些全局的键盘码别名

Vue.config.keyCodes.f2 = 113

10. 如何在全局和局部注册一个自定义的指令

全局注册主要是通过Vue.directive方法进行注册

Vue.directive第一个参数是指令的名字(不需要写上v-前缀),第二个参数可以是对象数据,也可以是一个指令函数

// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
  // 当被绑定的元素插入到 DOM 中时……
  inserted: function (el) {
    // 聚焦元素
    el.focus()  // 页面加载完成之后自动让输入框获取到焦点的小功能
  }
})

局部注册通过在组件options选项中设置directive属性

directives: {
  focus: {
    // 指令的定义
    inserted: function (el) {
      el.focus() // 页面加载完成之后自动让输入框获取到焦点的小功能
    }
  }
}

然后你可以在模板中任何元素上使用新的 v-focus property,如下:

<input v-focus />

11. 简单介绍一下你的开源项目和作品

设置页面登录权限和路由守卫,keep-alive缓存组件,对搜索功能进行防抖节流,图片和路由懒加载,UI组件库按需加载,transition实现页面渐入渐出,跨域请求设置,axios请求简单封装,对密码进行md5加密,后端node中使用jwt签发token,后端node中使用中间件集中处理错误

深圳(200-250 / 天)

1. 什么是事件委托

事件委托是一种提高程序性能,降低内存空间的技术手段,它利用了事件冒泡的特性,只需要在某个祖先元素上注册一个事件,就能管理其所有后代元素上同一类型的事件,而不需要给子元素一个一个的注册事件。

用一个例子来描述委托,先创建一个HTML文档,包含一个容器元素,以及它的3个子元素。

<div id="delegation">
    <button type="button">提交</button>
    <button type="button">返回</button>
    <button type="button">重置</button>
</div>

然后只要给容器元素注册点击事件,它的3个子元素也就能执行这个点击事件,这其实就是一种委托,再通过事件对象的target属性,就能分辨出当前运行在哪个事件目标上。

    var container = document.getElementById("delegation")
    container.addEventListener("click",function(event)
    {
        event.target;
    },false);

使用委托后就能避免对容器中的每个子元素进行事件注册,并且如果在容器中动态添加子元素,新加入的子元素也能使用容器元素上注册的事件,而不用单独绑定一次事件处理程序。

2. 什么是盒模型

CSS 盒模型本质上是一个盒子,它包括:边距,边框,填充和实际内容。

CSS 中的盒子模型包括 IE 盒子模型和标准的 W3C 盒子模型。

在标准的盒子模型中,width 指 content 部分的宽度。 在 IE 盒子模型中,width 表示 content+padding+border 这三个部分的宽度

故在计算盒子的宽度时存在差异:

标准盒模型: 一个块的总宽度 = width+margin(左右)+padding(左右)+border(左右)

怪异盒模型: 一个块的总宽度 = width+margin(左右)(既 width 已经包含了 padding 和 border 值)

3. 让一个元素水平垂直居中

  • 水平居中

    • 对于 行内元素 : text-align: center;

    • 对于确定宽度的块级元素:

      (1)width和margin实现。margin: 0 auto;

      (2)绝对定位和margin-left: (父width - 子width)/2, 前提是父元素position: relative

    • 对于宽度未知的块级元素

      (1)inline-block实现水平居中方法。display:inline-block和text-align:center实现水平居中。

      (2)绝对定位+transform,translateX可以移动本身元素的50%。

      (3)flex布局使用justify-content:center

  • 垂直居中

    1. 利用 line-height 实现居中,这种方法适合纯文字类、
    2. 弹性布局 flex :父级设置display: flex; 子级设置margin为auto实现自适应居中
    3. 父级设置相对定位,子级设置绝对定位,并且通过位移 transform 实现
    4. table 布局,父级通过转换成表格形式,然后子级设置 vertical-align 实现。(需要注意的是:vertical-align: middle使用的前提条件是内联元素以及display值为table-cell的元素)。

4. 做一个收起展开的动画效果,需要注意什么问题?怎么解决?

在设计和实现收起展开的动画效果时,您需要注意以下问题,并可以采取相应的解决方法:

  1. 动画的流畅性

    • 使用硬件加速:利用CSS属性如transformopacity来触发GPU加速,以提高动画的性能和流畅度。
    • 优化动画帧率:确保动画的帧率适中,一般目标是60帧/秒。可以使用requestAnimationFrame函数来优化动画的帧率。
  2. 用户体验

    • 响应式交互:考虑用户交互方式,如点击按钮或手势,以触发收起展开的动画。确保按钮或区域的大小和位置合适,易于点击或触摸。
    • 合理的动画速度:根据内容的大小和复杂度,选择合适的动画速度,以确保动画既不太快以至于无法看清,也不太慢以至于让用户等待过长时间。
  3. 设备兼容性

    • 浏览器兼容性:使用现代的Web标准和技术,确保您的动画在主流的浏览器上都能正常运行。在设计时可以参考各浏览器对CSS和JavaScript的支持情况,并进行兼容性测试。
    • 移动设备优化:针对移动设备,考虑使用轻量级的动画效果,避免过多的资源消耗和性能问题。
  4. 响应式设计

    • 弹性布局:使用弹性布局(Flexbox)或网格布局(Grid)等技术,确保动画在不同屏幕尺寸和设备方向下都能正常工作。这样可以实现自适应的效果,并提供一致的用户体验。
    • 媒体查询:根据不同的屏幕尺寸,使用媒体查询来调整动画的样式和布局,以适应不同的设备。
  5. 可访问性

    • 提供适当的键盘可访问性:确保用户可以使用键盘来触发和控制收起展开效果。在事件监听器中,监听键盘事件(如 Enter 或 Space 键),并根据键盘操作来切换显示状态。
    • 更新可访问性属性:根据显示状态的变化,通过 JavaScript 更新相应的可访问性属性,如 aria-expandedaria-hidden

5. 设备像素比是怎么算出来的?

在前端开发中,设备像素比(Device Pixel Ratio)是由浏览器提供的属性来获取的。可以使用JavaScript代码来获取设备像素比,示例如下:

var devicePixelRatio = window.devicePixelRatio || 1;

上述代码中,window.devicePixelRatio是浏览器提供的属性,它返回当前设备的像素比。如果浏览器不支持devicePixelRatio属性,那么我们可以将像素比设置为默认值1。

设备像素比表示设备上物理像素与CSS像素之间的比率。例如,如果设备像素比为2,那么表示设备上每个CSS像素由4个物理像素来呈现(2个水平方向的物理像素和2个垂直方向的物理像素)。

在响应式网页设计中,我们可以使用设备像素比来针对不同的设备像素密度提供适当的样式和图像资源,以确保网页在不同设备上以高清晰度显示。

6. 怎么理解JavaScript是一个单线程的语言?

理解JavaScript是单线程语言的核心概念是指在 JavaScript 运行时环境中,只有一个主线程来执行代码。这意味着 JavaScript 代码中的任务按顺序一个接一个地执行,每个任务需要等待前一个任务完成后才能执行。

以下是解释 JavaScript 单线程的几个关键点:

  1. 事件循环(Event Loop):JavaScript 运行时环境使用事件循环机制来管理任务的执行。事件循环会不断地从任务队列中取出任务并执行,直到队列为空。这样可以保证任务按顺序执行,避免了多个线程之间的竞争条件。

  2. 阻塞特性JavaScript 的单线程特性意味着当执行一个任务时,如果遇到阻塞(比如网络请求、文件读写等耗时操作),整个线程都会被阻塞,无法执行其他任务。这也就是为什么在 JavaScript 中执行大量计算或者长时间的操作会导致页面失去响应的原因。

  3. 异步编程:为了克服 JavaScript 单线程的阻塞特性,JavaScript 提供了异步编程的机制。通过使用回调函数、Promise、async/await 等方式,可以在执行耗时操作时注册回调函数,让 JavaScript 在等待结果的同时继续执行其他任务,从而提高了代码的并发性和响应性。

需要注意的是,尽管 JavaScript 运行在单线程上,但是浏览器或者运行时环境本身是多线程的。例如,浏览器中有渲染线程、网络线程、定时器线程等,这些线程与 JavaScript 主线程是并行执行的,使得浏览器可以同时进行多个任务,提供更好的用户体验。

7. 你讲一下EventLoop这个机制

## JS的Event Loop你能给我介绍下吗?

8. 宏任务微任务有哪些?

浏览器中的任务源(task):

  • 宏任务(macrotask): 宿主环境提供的,比如浏览器 ajax、setTimeout、setInterval、setTmmediate(只兼容ie)、script、requestAnimationFrame、UI渲染、一些浏览器api,I/O 操作(例如网络请求、文件读写等异步操作)。
  • 微任务(microtask): 语言本身提供的,比如promise.then then、mutationObserver(浏览器提供,监测 DOM 变化的回调函数被放入微任务队列中)、process.nextTick(仅在 Node.js 环境中,在当前执行完成后立即执行的回调函数)

9. 重排和重绘有什么区别?

##  渲染页面的重绘回流你能给我讲一下吗?

10. 哪些样式属性会触发重排?

  1. 修改元素的尺寸:改变元素的宽度、高度、边距(margin)、内边距(padding)、边框(border)等属性会导致重排。这是因为重排需要重新计算元素在布局中的位置。
  2. 修改元素的位置:改变元素的定位方式(position)和偏移量(top、left、right、bottom)会触发重排。这是因为元素位置的变化可能会导致其他元素的重新布局。
  3. 修改元素的显示属性:修改元素的显示属性(display)会导致重排。例如,从隐藏(display: none)变为可见(display: block)或反之。
  4. 修改字体样式:改变文本的字体大小、字体粗细、行高等属性也可能触发重排。这是因为文字的尺寸变化可能会导致周围元素重新调整布局。
  5. 修改浏览器窗口尺寸:调整浏览器窗口的大小会导致页面中的元素重新布局,从而触发重排。

11. 开发过程中的跨域要怎么处理?

## 那你有遇到过跨域问题吗?实际解决方法?

12. 什么是强缓存?什么是弱缓存?

  • 强制缓存

    强制缓存就是向浏览器缓存查找该请求结果,并根据该结果的缓存规则来决定是否使用该缓存结果的过程。当浏览器向服务器发起请求时,服务器会将缓存规则放入HTTP响应报文的HTTP头中和请求结果一起返回给浏览器,控制强制缓存的字段分别是 ExpiresCache-Control,其中Cache-Control优先级比Expires高。

    强制缓存的情况主要有三种(暂不分析协商缓存过程),如下:

    1. 不存在该缓存结果和缓存标识,强制缓存失效,则直接向服务器发起请求(跟第一次发起请求一致)。
    2. 存在该缓存结果和缓存标识,但该结果已失效,强制缓存失效,则使用协商缓存。
    3. 存在该缓存结果和缓存标识,且该结果尚未失效,强制缓存生效,直接返回该结果
  • 协商缓存

    协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程,同样,协商缓存的标识也是在响应报文的HTTP头中和请求结果一起返回给浏览器的,控制协商缓存的字段分别有:Last-Modified / If-Modified-SinceEtag / If-None-Match,其中Etag / If-None-Match的优先级比Last-Modified / If-Modified-Since高。协商缓存主要有以下两种情况:

    1. 协商缓存生效,返回304
    2. 协商缓存失效,返回200和请求结果结果

这里吐句槽,直接问强缓存和弱缓存太突然了,应该先问HTTP的状态码,然后从状态码中的304引申到强弱缓存的,所以大家记得也看看HTTP有哪些的状态码,记住一些常用的即可http状态码详细介绍(200,301,304,403,404,500),以及首数字开头分别代表什么

介绍下304过程

  • a. 浏览器请求资源时首先命中资源的Expires 和 Cache-Control,Expires 受限于本地时间,如果修改了本地时间,可能会造成缓存失效,可以通过Cache-control: max-age指定最大生命周期,状态仍然返回200,但不会请求数据,在浏览器中能明显看到from cache字样。
  • b. 强缓存失效,进入协商缓存阶段,首先验证ETagETag可以保证每一个资源是唯一的,资源变化都会导致ETag变化。服务器根据客户端上送的If-None-Match值来判断是否命中缓存。
  • c. 协商缓存Last-Modify/If-Modify-Since阶段,客户端第一次请求资源时,服务服返回的header中会加上Last-Modify,Last-modify是一个时间标识该资源的最后修改时间。再次请求该资源时,request的请求头中会包含If-Modify-Since,该值为缓存之前返回的Last-Modify。服务器收到If-Modify-Since后,根据资源的最后修改时间判断是否命中缓存。

13. 讲一下vue的生命周期?

## Vue生命周期的执行顺序?

14. vue的父子组件传递参数有几种?

## 有五个组件嵌套,Vue中实现这些组件传值的方法有哪些?

15. 你的项目中是怎么适应不同尺寸的手机屏幕?

我用的就是直接用了一个组件,就是lib-flexible,淘宝项目组开发出来的开源库,它的原理就是把自动将css中的px转换成rem

如果要自己做的话,也就是做一个响应式的布局。

  1. CSS媒体查询:使用CSS媒体查询可以检测设备的屏幕尺寸、分辨率和方向等特性,并根据这些特性应用不同的样式规则。通过定义不同的CSS样式,可以使网页在不同的设备上以不同的方式呈现。

  2. 百分比%:比如当浏览器的宽度或者高度发生变化时,通过百分比单位,通过百分比单位可以使得浏览器中的组件的宽和高随着浏览器的变化而变化,从而实现响应式的效果。

  3. vw/vh:css3中引入了一个新的单位vw/vh,与视图窗口有关,vw表示相对于视图窗口的宽度,vh表示相对于视图窗口高度。 任意层级元素,在使用vw单位的情况下,1vw都等于视图宽度的百分之一。

  4. rem:rem单位是相对于字体大小的html元素(即html元素的font-size),也称为根元素,所以只需要获取设备的宽度,然后再结合设计稿,进行一个计算,算出比例把font-size修改一下即可。

16. TypeScript的话了解多少?

TypeScript的话一开始先了解基本语法和类型约束,然后自己也尝试着在项目中使用。

我后端项目中也就是基于TypeScript,对参数进行简单的一些约束,并且在后端Koa项目中也结合了ts封装一些简单的hooks函数。

17. 什么是函数重载?

在一些后端语言里面,有函数重载这样一个概念,允许在同一范围内指定多个同名函数。这些函数称为重载函数或重载。 比如下面代码中的foo

function foo(x: number): number;
function foo(x: string): string;
function foo(x: number | string):  number | string {
  if (typeof x === 'number') {
    return x * 2;
  } else if (typeof x === 'string') {
    return 'Hello, ' + x;
  }
}

const result1 = foo(10); // result1 的类型为 number
const result2 = foo('world'); // result2 的类型为 string

利用重载函数,你可以根据函数返回值的类型和数量为函数提供不同的语义。而ts也提供了函数重载的功能。我们可以利用函数重载,为这个函数的返回值提供多个类型定义。

声明多个相同名称的函数,给他们设置多个不同的入参类型和返回类型。在我们调用这个重载函数的时候,TS会把函数返回值的类型与定义中的类型进行比较,决定选用最合适的定义类型。

18. vue3里的reactive和ref有什么区别?

在Vue 3中,reactiveref是用于创建响应式数据的两种不同方式。

reactive函数用于将一个普通的JavaScript对象转换为响应式对象。它会递归地将对象的所有属性转换为响应式属性,这意味着当属性的值发生变化时,Vue会自动追踪和更新相关的视图。使用reactive函数创建的对象可以像普通对象一样使用,可以直接访问和修改属性。

import { reactive } from 'vue'

const state = reactive({
  count: 0
})

console.log(state.count) // 输出: 0
state.count++ // 修改count的值
console.log(state.count) // 输出: 1

ref函数用于创建一个简单的响应式引用。它将一个普通的JavaScript值转换为一个响应式对象,该对象具有一个名为value的属性,该属性包含实际的值。与reactive不同,ref只能用于包装单个值,而不是对象。

import { ref } from 'vue'

const count = ref(0)

console.log(count.value) // 输出: 0
count.value++ // 修改值
console.log(count.value) // 输出: 1

当在模板中使用响应式对象时,可以直接访问ref包装的值,而不需要访问.value属性。Vue会自动进行解包。

<template>
  <div>
    <p>Count: {{ count }}</p>
    <button @click="increment">Increment</button>
  </div>
</template>

<script>
import { ref } from 'vue'

export default {
  setup() {
    const count = ref(0)

    const increment = () => {
      count.value++
    }

    return {
      count,
      increment
    }
  }
}
</script>

综上所述,reactive用于创建响应式对象,适用于复杂的数据结构,而ref用于创建简单的响应式引用,适用于单个值。

北京(300-400 / 天)

该家面试官主要是针对我的简历和项目进行询问的,不是简单得直接上来就问八股。

1. 用chatgpt写过代码吗?

  1. ChatGPT可以用于生成动态数据展示和可视化,例如通过调用图表库(如EChartsD3.js)来生成柱状图、折线图等,展示数据趋势和统计信息。
  2. 动画效果:ChatGPT可以编写代码实现各种动画效果,如淡入淡出滑动旋转等,通过CSS或JavaScript动画库实现页面元素的动态效果。
  3. 用户界面交互:ChatGPT可以快速编写前端界面的用户交互逻辑,例如处理用户输入验证表单数据展示提示错误信息等。

2. 你为什么选择做懂XXX这个项目?

  1. 兴趣和热情:表达你对汽车行业的兴趣和热情,说明你对懂车帝项目的内容和目标感兴趣。可以提到你喜欢汽车,对汽车相关的科技和创新有浓厚的兴趣

  2. 行业前景和发展机会:强调汽车行业的巨大潜力和发展机会。提到汽车行业是一个充满挑战和创新的领域,随着智能汽车、电动化和可持续交通的兴起,对技术和解决方案的需求不断增加。指出参与懂车帝项目可以接触到前沿的汽车技术和行业趋势,并在这个快速发展的领域中有机会成长和发展。

  3. 项目的价值和影响:强调懂车帝项目的价值和影响力。可以提到该项目致力于提供汽车相关的信息、服务和解决方案,帮助用户更好地了解、选择和使用汽车。并且仿写这个项目能大致了解一下懂车帝团队中是如何做一个项目的,之后进行深入学习和了解设计理念。

3. KOA我还没了解,KOA是什么啊?

Koa是一个基于Node.js的Web应用框架,旨在提供更简洁更优雅的方式来构建Web应用程序。Koa由Express框架的原作者团队开发,旨在解决Express框架中存在的一些问题,并引入了一些新的概念和功能。

  • Koa采用了中间件的概念,允许开发者通过编写各种功能单一的中间件来组合构建复杂的应用逻辑。并且引入了洋葱模型的概念,即每个中间件都可以对请求和响应进行处理,并将控制权传递给下一个中间件,使得应用的逻辑更加清晰、模块化。
  • Koa还提供了上下文对象(Context),封装了每个请求和响应的信息,方便开发者处理请求和响应。
  • 虽然Koa本身不提供路由功能,但可以使用第三方中间件如koa-router来实现路由功能。
  1. 数据库都建的是什么表呢?

5. 对登录密码进行MD5加密,这个是什么意思?

用户登录后会把账号和密码传给后端,后端接收需要把密码存入到数据库中,但这时就涉及到了安全性的问题,用户传来的密码是一个明文,使用明文存储容易被窃取,所以就需要一个加密的手段,后端服务器使用md5对其加密增加密码的安全性。

MD5是一种常用的密码加密算法,它将明文密码转换为一个128位的散列值。通过使用MD5加密,可以隐藏原始密码的真实值,使得在存储和传输过程中更难以被窃取或破解。

6. md5和bcryptjs加密的区别

MD5(Message Digest Algorithm 5)和bcryptjs都是常见的加密算法,但它们在加密方式、安全性和用途上存在一些区别。

  1. 加密强度

    • MD5:MD5 算法的加密强度较低,因为其较短的哈希长度(128位),使得通过穷举法破解哈希值相对容易。
    • bcrypt.js:bcrypt.js 算法的加密强度较高,通过增加迭代次数和随机盐值的使用,可以大大增加破解的时间和计算资源成本。
  2. 安全性

    • MD5:MD5 是一种较早的算法,已经被广泛研究和攻击。它容易受到碰撞(collision)和彩虹表(rainbow table)攻击的影响。但由于其快速计算性能,MD5 可以用于一些对性能追求高的存储数据,但不推荐用于存储密码或敏感数据。
    • bcryptjs:bcryptjs 是一种更安全的密码散列函数。它引入了盐和可调节的迭代次数,这增加了破解密码的难度。通过增加计算成本,bcryptjs 可以有效地防止暴力破解和彩虹表(rainbow table)攻击。
  3. 用途

    • MD5:MD5 算法主要用于数据校验、唯一标识和非安全性的散列需求。例如,校验文件完整性或生成简单的校验和。
    • bcrypt.js:bcrypt.js 算法主要用于用户密码的存储和验证,适用于任何需要存储用户密码的应用程序。

7. 验证用户身份这块你是怎么做的

  • 用户先进行一个登录,登录后前端传给后端用户的账号和密码,然后从数据库中进行匹对,找到该用户的ID,之后把这个ID用全局变量环境.env文件中配置的密钥进行一个签证令牌的操作,这时候ID就编程了加密后的token,紧接着把token返回给前端浏览器,并把token存入本地存储localStore中做一个用户数据持久化。

  • 之后我使用axios设置了一个请求头,从本地存储localStore中拿到token并放入请求头中,当用户每次发送一个请求时,后端服务器都会拿到这个token,再使用公钥进行一个解码拿到用户的ID,匹配数据库中相应的用户信息,从而完成了一个验证身份功能。

8. 为什么使用非对称加密?

使用非对称加密有以下几个主要原因:

  1. 安全性:非对称加密提供了更高的安全性。在非对称加密中,有一对密钥,一个是公钥,一个是私钥。公钥可以自由发布给任何人,而私钥必须保密。通过使用公钥加密数据,只有持有相应私钥的实体才能解密和访问数据。这种机制提供了更好的保护,因为即使公钥泄露,攻击者也无法解密数据。
  2. 密钥交换:非对称加密还可以用于密钥交换过程。在通信双方建立安全通信之前,它们可以使用非对称加密来交换密钥。其中一方使用对方的公钥加密一个随机生成的会话密钥,并将其发送给对方。只有拥有相应私钥的对方才能解密该会话密钥。接下来,双方可以使用该会话密钥来进行对称加密通信,这样可以提供更高的效率和性能。
  3. 数字签名:非对称加密还用于生成和验证数字签名。通过使用私钥对数据进行签名,可以确保数据的完整性和认证性。接收方可以使用相应的公钥来验证签名,确保数据没有被篡改,并且确实来自预期的发送方。

需要注意的是,非对称加密算法的计算复杂度相对较高,因此在处理大量数据时可能会影响性能。为了兼顾安全性和性能,通常会使用非对称加密与对称加密相结合的方式,例如在密钥交换阶段使用非对称加密,而在通信阶段使用对称加密来提供更高的效率和安全性。

9. stylus我还没用过,解释一下

Stylus是一种CSS预处理器,与其他预编译语言(如Sass、Less)相比,它具有一些独特的特点和区别。

以下是Stylus与其他预编译语言的主要特点和区别:

  1. 语法差异:Stylus具有非常简洁的语法,使用缩进而不是大括号来表示代码块。相比之下,Sass和Less使用大括号和分号来定义和分隔代码块。
  2. 变量定义:在Stylus中,变量定义时不需要使用特殊的符号(如$符号),而是直接使用变量名。这使得Stylus的变量定义更加简洁。
  3. 混合(Mixins)功能:Stylus的混合功能与Sass和Less类似,可以定义一组样式规则并在需要时重复使用。然而,Stylus的混合语法更加灵活,并支持传递参数的方式与其他预编译语言有所不同。
  4. 嵌套规则:Stylus支持使用嵌套规则,使样式的层次结构更加清晰。相比之下,Sass和Less也支持嵌套规则,但它们使用的是选择器组合的方式。
  5. 代码压缩:Stylus提供了内置的代码压缩选项,可以将样式表压缩为单行,减少文件大小。相比之下,Sass和Less也提供了类似的压缩功能。
  6. 插件生态系统:Sass和Less都有丰富的插件生态系统,提供了许多额外的功能和扩展。相比之下,Stylus的插件生态系统相对较小,可用的插件和工具相对较少。

总体而言,Stylus的主要特点是简洁的语法、灵活的变量定义和混合功能、清晰的嵌套规则以及内置的代码压缩选项。它与其他预编译语言在语法和功能上存在一些差异,开发者可以根据个人偏好和项目需求选择合适的预编译语言。

10. 项目中有其他难题

面试:(简单粗暴点)百度一面,直接问痛我第十一题

11. 你搜索框输入时关联用的防抖讲一下

function debounce(func, delay) {
    return function (...args) {
        let that = this
        clearTimeout(func.tid)
        func.tid = setTimeout(function () {
            func.call(that, ...args)
        }, delay)
    }
}

12. HTTP的版本做了哪些改动?

  1. HTTP/0.9(1991):

    • 仅支持GET方法,用于请求服务器上的静态HTML文件。
    • 响应内容仅为纯文本
  2. HTTP/1.0(1996):

    • 引入了更多的HTTP方法,如POSTHEADPUT等,支持RESTful架构。
    • 引入了请求头响应头,包括状态码、字符集、多部分发送和代理等。
    • 引入了Cookie机制,允许服务器在客户端保存状态信息。
    • 支持构建Web应用程序,涉及B/S(浏览器/服务器)和C/S(客户端/服务器)架构。
  3. HTTP/1.1(1999):

    • 引入了持久化连接(Keep-Alive),允许多个请求和响应共享同一个TCP连接,减少了连接建立的开销。
    • 引入了管道传输(Pipelining),允许在同一个TCP连接上发送多个请求,提高了性能。
    • 引入了缓存机制,包括Cache-Control和其他相关指令,可以对缓存进行更精细的控制。
    • 引入了虚拟主机(Virtual Host),允许在单个服务器上托管多个域名,并根据请求的Host头字段来区分不同的虚拟主机。
  4. HTTP/2(2015):

    • 引入了多路复用(Multiplexing)的能力,允许在同一个TCP连接上同时发送多个请求和响应,提高了并发性能。
    • 使用二进制分帧(Binary Framing)进行数据传输,将请求和响应拆分为多个帧,并进行无序的交错传输,提高了传输效率。
    • 支持服务器推送(Server Push),服务器可以在客户端请求前主动推送资源,提高了性能。
    • 改进了头部压缩机制,减少了传输的数据量。
  5. HTTP/3(正在开发中,处于草案当中):

    • 基于基于UDP的传输协议QUIC(Quick UDP Internet Connections)。
    • 引入了可靠的数据传输机制,解决了UDP丢包的问题。
    • 支持多路复用,减少了网络延迟。
    • 具备快速连接建立和迁移功能。
    • 提升了安全性,通过TLS 1.3进行加密。

13. 了解vue3的响应式底层原理,讲一下?

14. 假如说你有几个offer的话,你怎么选择offer,最看重的是什么?

  1. 公司文化和价值观:了解每个公司的文化、团队氛围和核心价值观,看看它们是否与你的价值观和工作风格相匹配。重要的是,在一个能够提供良好学习和成长机会的环境中工作。强调你对学习和成长的渴望,以及希望在一个积极的、支持性的环境中工作。你可以说你会优先选择那些提供学习机会和成长空间的岗位。

  2. 项目和技术:了解每个实习岗位的具体项目和技术栈,以及你将有机会学习和使用的技术。选择一个能够提供广泛技术经验和发展前景的项目是很重要的。提及项目和技术方面的重要性,强调你对接触不同技术栈和有挑战性的项目感兴趣,因为这将帮助你扩展你的技能和经验。

  3. 导师和团队支持:了解每个实习岗位是否会有导师或者团队成员指导和支持你的成长。选择一个有良好指导和支持体系的岗位可以加速你的学习和职业发展。指出导师和团队支持对你职业发展的重要性,强调你愿意在一个能够得到指导和支持的团队中工作,并且有机会与经验丰富的导师合作。

上面的回答仅供参考,最终还得结合一下公司的具体方面来答。

结语

都七月初了,该润得早都润了,那就沉淀沉淀吧。

转载自:https://juejin.cn/post/7250513276237070373
评论
请登录