面试题归纳

144 阅读12分钟

1.实现元素水平居中的方法

  1.弹性布局 主轴和垂直轴 居中

  2.弹性布局  父元素display: flex  子元素 margin: auto

  3.定位  父元素 相对定位  子元素绝对定位  上下左右为0  margin: auto

  4.父元素 display : grid place-content: center center

2. webpack 构建流程

webpack 启动以后, 从 entry 开始, 递归解析所有 entry 依赖的所有 module ,在找到每一个 module 的时候,就会根据 module.rules 里配置的 loader 进行相应的转换, 对 module 转化后在解析 module 依赖的一些其他模块, 解析的结果是一个一个 chunk , 然后 webpack 会将所有的 chunk 转化成文件输出的 output . 在整个构建过程中, webpack 会执行 plugin 当中的插件, 完成 plugin 的任务

entry : 模块入口, 使得源文件加入到构建流程中

output : 出口

module :配置各种模块处理规则

plugin : 配置插件

loader : 用于对模块的源代码进行转化

3.vue 双向绑定的原理

  • vue数据双向绑定是通过 数据劫持 结合 发布者-订阅者模式 的方式来实现的.
  • vue是通过Object.defineProperty()来实现数据劫持的。它可以来控制一个对象属性的一些特有操作,比如读写权、是否可以枚举.有get和set两个方法。
  • 实现mvvm主要包含两个方面,数据变化更新视图,视图变化更新数据。视图更新数据其实可以通过事件监听即可,关键在于数据变化更新视图,通过Object.defineProperty( )对属性设置一个set函数,当数据改变了就会来触发这个函数,所以我们只要将一些需要更新的方法放在这里面就可以实现data更新view了。
  • 实现数据的双向绑定:
  1. 实现一个监听器 Observer:  对数据对象进行遍历,包括子属性对象的属性,利用 Object.defineProperty() 对属性都加上 setter 和 getter。这样的话,给这个对象的某个值赋值,就会触发 setter,那么就能监听到了数据变化
  2. 实现一个解析器 Compile:  解析 Vue 模板指令,将模板中的变量都替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,调用更新函数进行数据更新。
  3. 实现一个订阅者 Watcher:  Watcher 订阅者是 Observer 和 Compile 之间通信的桥梁 ,主要的任务是订阅 Observer 中的属性值变化的消息,当收到属性值变化的消息时,触发解析器 Compile 中对应的更新函数。
  4. 实现一个订阅器 Dep:  订阅器采用 发布-订阅 设计模式,用来收集订阅者 Watcher,对监听器 Observer 和 订阅者 Watcher 进行统一管理

Snipaste_2022-09-19_13-41-16.png

4.组件封装

组件: 简单来说就是一段可以复用的功能代码. 封装好之后, 用一行简单的代码, 就可以实现一个复杂的功能.

组件传值 和 插槽

大体的步骤:

  1. 在 components 文件夹中新建一个 vue 文件
  2. 在 main.js 中全局引入, 先 import 再注册到 VUE 中
  3. 接着就可以在任何页面直接使用自己定义的的组件

使用Vue.extend方法创建一个组件,然后使用Vue.component方法注册组件。但是我们一般用脚手架开发项目,每个 .vue单文件就是一个组件。在另一组件import 导入,并在components中注册,子组件需要数据,可以在props中接受定义。而子组件修改好数据后,想把数据传递给父组件。可以采用emit方法。

5.组件传值

1.props / $emit

2.ref 与 parent/ parent /children

3.eventbus

4.provide / inject 隔代组件通信

5.vuex 状态管理器

多个视图依赖于同一状态。

来自不同视图的行为需要变更同一状态

state ; 状态

getter : 从基本数据派生的数据

6.axios的二次封装

为什么封装要二次封装

axios的 API 其实很友好了 , 完全可以很轻松的使用 不过随着项目规模增大, 如果每发起一次 HTTP 请求, 就要把这些比如设置请求时间,设置请求头,根据项目环境判断使用哪个请求地址,错误处理等操作, 都要写一遍, 这种重复劳动不仅浪费时间,而且使代码变得骸余. 为了提高我们代码质量,所以要二次封装

如何封装

1.1 安装axios

1.2 通常情况下, 项目都要一个 api 文件夹(axios 二次封装的文件夹)

a.创建一个 api 文件夹
b.在 api 文件夹下创建 request.js (用于书写 axios 二次封装的代码)
c.在 request.js 书写 axios 二次封装的代码(引入axios   利用axios对象的方法create 创建axios实例 然后配置)
d.对api 进行统一的管理(请求接口比较多,需要统一进行管理)

2. 在 api 文件夹新建一个 index.js 用于管理接口

  1. 在index.js 书写代码

7.vue路由导航守卫

全局前置/钩子 : beforeEach , beforeResolve , afterEach

路由独享守卫 : beforeEnter

组件内的守卫 : beforeRouteEnter , beforeRouteUpdata , beforeRouteLeave

8.watch 和 computed 的区别

computed 计算属性 : 依赖其他属性值 , 并且computed 的值有缓存, 只有依赖它的属性值发生变化,下次获取 computed 的值时才会计算 computed 的值

watch 侦听器 : 更多的是观察作用, 无缓存性 , 类似于某些数据监听回调, 每当监听的数据变化时都会执行回调进行后续操作

使用场景

当需要进行数值计算, 并且依赖于其他数据时, 应该使用 computed , 因为可以利用 computed 的缓存特性,避免每次获取值的时候需要重新计算

当需要在数据变化时执行异步或者开销较大的操作时, 应该使用 watch ,使用 watch 选项允许执行异步操作时, 应该使用 watch , 使用 watch 选项允许执行异步操作(访问一个API ),限制执行该操作的频率, 并最终到结果前, 设置中间状态. 这些都是计算属性无法做到的

9. var let 和 const 区别

(1)块级作用域: 块作用域由 { }包括,let和const具有块级作用域,var不存在块级作用域。块级作用域解决了ES5中的两个问题:

  • 内层变量可能覆盖外层变量
  • 用来计数的循环变量泄露为全局变量

(2)变量提升: var存在变量提升,let和const不存在变量提升,即在变量只能在声明之后使用,否在会报错。

(3)给全局添加属性: 浏览器的全局对象是window,Node的全局对象是global。var声明的变量为全局变量,并且会将该变量添加为全局对象的属性,但是let和const不会。

(4)重复声明: var声明变量时,可以重复声明变量,后声明的同名变量会覆盖之前声明的遍历。const和let不允许重复声明变量。

(5)暂时性死区: 在使用let、const命令声明变量之前,该变量都是不可用的。这在语法上,称为暂时性死区。使用var声明的变量不存在暂时性死区。

(6)初始值设置: 在变量声明时,var 和 let 可以不用设置初始值。而const声明变量必须设置初始值。

(7)指针指向: let和const都是ES6新增的用于创建变量的语法。 let创建的变量是可以更改指针指向(可以重新赋值)。但const声明的变量是不允许改变指针的指向。

Snipaste_2022-09-21_14-54-23.png

**10. 节流和防抖 **

节流: n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效 防抖: n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时

相同点:

  • 都可以通过使用 setTimeout 实现
  • 目的都是,降低回调执行频率。节省计算资源

不同点:

  • 函数防抖,在一段连续操作结束后,处理回调,利用clearTimeout和 setTimeout实现。函数节流,在一段连续操作中,每一段时间只执行一次,频率较高的事件中使用来提高性能
  • 函数防抖关注一定时间连续触发的事件,只在最后执行一次,而函数节流一段时间内只执行一次

防抖在连续的事件,只需触发一次回调的场景有:

  • 搜索框搜索输入。只需用户最后一次输入完,再发送请求
  • 手机号、邮箱验证输入检测
  • 窗口大小resize。只需窗口调整完成后,计算窗口大小。防止重复渲染。

节流在间隔一段时间执行一次回调的场景有:

  • 滚动加载,加载更多或滚到底部监听
  • 搜索框,搜索联想功能

11. 回流 和 重绘

当渲染树中的⼀部分(或全部)因为元素的规模尺⼨,布局,隐藏等改变⽽需要重新构建。这就称为回流(reflow)

当渲染树中的⼀些元素需要更新属性,⽽这些属性只是影响元素的外观,⻛格,⽽不会影响布局的,则就称为重绘 color ,border-style, border-radius, background

两者区别:

回流必将引起重绘,⽽᯿绘不⼀定会引起回流。⽐如:只有颜⾊改变的时候就只会发⽣重绘⽽不会引起回流

当⻚⾯布局和⼏何属性改变时就需要回流

12. vue 数据双向绑定

  1. new Vue()首先执行初始化,对data执行响应化处理,这个过程发生Observe
  2. 同时对模板执行编译,找到其中动态绑定的数据,从data中获取并初始化视图,这个过程发生在Compile
  3. 同时定义⼀个更新函数和Watcher,将来对应数据变化时Watcher会调用更新函数
  4. 由于data的某个key在⼀个视图中可能出现多次,所以每个key都需要⼀个管家Dep来管理多个Watcher
  5. 将来data中数据⼀旦发生变化,会首先找到对应的Dep,通知所有Watcher执行更新函数

Snipaste_2022-09-22_09-44-43.png

13.数组去重的方式

1.双重 for 循环

  1. for 循环 + findindex

3.sort 排序

4.set

5.set + Array.form

6.filter + indexOf

7.includes

8.for + object

9.for + splice

10.filter + indexOf

11.Map

12.reduce

14. 谈谈cookie,sessionStorage和localStorage

相同点:

cookie、sessionStorage和localStorage都⽤在客户端存储数据,每⼀个都有⾃⼰的存储和到期限制

不同点:

⼀、存储⼤⼩

cookie数据⼤⼩不能⼤于4K;

localStorage和sessionStorage则可以达到5M;

⼆、有效时间

cookie在设置的有效期内⼀直有效;

localStorage存储持久数据,只要不⼿动清除则⼀直存在;

sessionStorage数据在当前浏览器关闭后就会被⾃动清除

三、数据与服务器间的交互⽅式

cookie的数据会⾃动传递到服务器端,服务器端也可以写cookie到客户端

localStorage和sessionStorage不会把数据⾃动传到服务器端,仅在本地存储

15.谈谈防抖和节流

防抖节流就是使⽤定时器来实现我们的⽬的。

防抖(debounce):

在事件被触发n秒后再执⾏回调,如果在这n秒内⼜被触发,则重新计时。

典型的案例就是输⼊框搜索:输⼊结束后n秒才进⾏搜索请求,n秒内⼜输⼊的内容,则᯿新计时。

节流(throttle):

规定在⼀个单位时间内,只能触发⼀次函数,如果这个单位时间内触发多次函数,只有⼀次⽣效。

典型的案例就是⿏标不断点击触发,规定在n秒内多次点击只⽣效⼀次

为什么要掌握防抖和节流

函数节流与函数防抖都是可以限制函数的执⾏频次,根据不同的场景来对执⾏频率进⾏限制,避免了函数触发频率过⾼导致的响应速度跟不上触发频率,出现延迟,假死或卡顿的现象。

16.get 和 post 的区别

参数位置来看          get参数拼接到 url 后面                    post 参数在请求体中

 参数大小来看         get受限于 url 的大小,一般大小不超过32k    post 为 1G

服务器数据接受来看    get 接受一次                             post 根据数据大小, 可分多次接受

 适用场景来看         get 从服务端获取数据                    post 向服务端提交数据

 安全性              get 请求携带在 URL ,安全性较低           post 相对于 get 请求, 安全性较高

**17. 内存泄漏问题 **

指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。

场景:

  • 缓存:存在内存中数据一只没有被清掉
  • 作用域未释放(闭包)
  • 无效的 DOM 引用
  • 没必要的全局变量
  • 定时器未清除(React中的合成事件,还有原生事件的绑定区别)
  • 事件监听为清空
  • 内存泄漏优化

垃圾回收机制

原理:垃圾收集器会定期(周期性)找出那些不在继续使用的变量,然后释放其内存

1.标记清除法

JavaScript最常用的垃圾收回机制

当变量进入执行环境是,就标记这个变量为“进入环境“。进入环境的变量所占用的内存就不能释放,当变量离开环境时,则将其标记为“离开环境“

垃圾回收程序运行的时候,会标记内存中存储的所有变量。然后,它会将所有在上下文中的变量,以及被在上下文中的变量引用的变量的标记去掉

在此之后再被加上标记的变量就是待删除的了,原因是任何在上下文中的变量都访问不到它们了

随后垃圾回收程序做一次内存清理,销毁带标记的所有值并收回它们的内存

2.引用计数

18.0.1+0.2!=0.3怎么处理

1.把计算数字 提升 10 的N次⽅ 倍 再 除以 10的N次⽅。N>1.

(0.110+ 0.210)/10== 0.3//true

2.四舍五⼊ tofixed

19.移动端适配

参考链接: 移动端如何适配

  • 在web中,浏览器为我们提供了window.devicePixelRatio来帮助我们获取dpr。
  • 在css中,可以使用媒体查询min-device-pixel-ratio,区分dpr:
@media (-webkit-min-device-pixel-ratio: 2),(min-device-pixel-ratio: 2){ }