前端面试题整理

627 阅读10分钟

面试题整理

浏览器

输入一个URL到页面过程中发生了什么

  1. DNS解析,将url解析为网站的IP
  2. 建立TCP连接
  3. 发起HTTP请求
  4. 服务器返回请求结果
  5. 关闭TCP连接
  6. 客户端渲染页面

客户端渲染页面的过程是怎样的

  1. 解析服务器返回的内容
  2. 建立DOM树
  3. 构建CSS树
  4. 构建render树, 构建CSSOM树,将DOM和CSS进行结合
  5. 布局—layout:计算出节点在页面中的位置
  6. 绘制—Painting:绘制节点到页面上

回流和重绘的区别

回流Layout:当渲染树中元素的尺寸、位置发生变化时会重新构建,重建构建时会影响布局,这个过程就称为回流

重绘Painting:当渲染树中元素的颜色或其他属性变化时会重新构建,构建时不影响布局,这个过程就是重绘

区别:

  • 回流肯定会引起重绘,重绘一定不会引起回流

  • 回流会导致页面重新排列,会影响性能

  • 回流会影响性能,那么如何避免回流?

    不要修改元素的尺寸、位置这些会影响布局的属性,尽量使用transform

TCP 传输的三次握手、四次挥手策略

三次握手

  • 第一次握手:客户端 请求 服务端
  • 第二次握手:服务端 回复 客户端
  • 第三次握手:客户端 回复 服务端

四次挥手

  • 第一次挥手:客户端 请求 服务端
  • 第二次挥手:服务端 回复 客户端
  • 第三次挥手:服务端 回复 客户端
  • 第四次挥手:客户端 回复 服务端

http 和 https 的区别

  • http端口是80 https端口是443
  • http是超文本传输协议,是明文传输;https是SSL协议,是加密传输
  • http连接简单,是无状态的。https是http和ssl证书构建的加密传输,是安全的。

HTTP常见的状态码

200

  • 200 请求成功

300

  • 301 永久重定向
  • 302 临时重定向

400

  • 401 身份认证有问题
  • 403 服务端拒绝访问
  • 404 找不到页面

500

  • 500 服务器问题,服务器没开或者有错误

什么是跨域?

发送请求时,客户端和服务端不是同源策略,也就是协议、域名、端口号一致的情况就是跨域。

同源策略:协议、域名、端口号一致

如何解决跨域?

  1. Cors跨域,需要后端配置

    header(“Access-Control-Allow-Origin:*”); // 允许任何来源
    header(“Access-Control-Allow-Origin:http://me.com”); //只允许来自域名http://me.com的请求
    
  2. 代理proxy

    • Vue: 在vue.config.js中devServer配置proxy
    • React: 使用http-proxy-middleware库配置跨域

浏览器本地存储

LocalStoreage周期: 永久,不删一直在。 位置: 浏览器本地 存储大小: 5MB 共享: 同源策略,不同浏览器窗口可以共享

SessionStorage: 周期: 临时,页面关闭不存在。 位置: 浏览器本地 存储大小: 5MB 共享: 同源策略,不同浏览器窗口不可以共享,即使同一个页面。

Cookie: 周期: 可以设置有效期,页面关闭不存在。 位置: 可以和浏览器通信 存储大小: 4k 共享: 同源策略窗口

防抖和节流的区别

  • 防抖:连续多次触发时,上一次没有执行完的时候,会清除上次执行的事件,执行本次新的事件
  • 节流:连续多次触发时,上一次没有执行完的时候,会清除本次执行的事件,执行上次的事件

防抖和节流的区别:防抖是无论执行多少次都执行最后一次,节流是n秒执行一次,减少执行次数。

浏览器缓存机制

首次访问页面的时候浏览器会讲页面缓存到本地,之后再次访问的时候会根据缓存策略决定使用缓存还是向服务器发送请求。

  • 浏览器的缓存策略有哪些

    • 强制缓存:强制使用缓存, 客户端通过Expires 、Cache-Control字段判断是否已过期,如果缓存未过期,直接使用缓存内容,如果已过期讲走协商缓存。
  • 协商缓存:当强制缓存失效后,会使用协商缓存。服务器通过Etag、Last-Modified字段判断是否过期,如果已过期,但文件未更新返回304,使用缓存; 如果文件已更新,返回请求的内容,状态200.

JavaScript

堆和栈的区别

  • 栈内存:基本类型会存放在栈内存中,存取方式为先进后出。
  • 堆内存:引用类型会存放在堆内存中

数据类型判断方式

  • typeof
  • instanceof
  • Object.prototype.toString.call(obj)

什么是闭包?如何实现闭包

闭包就是在函数外部访问函数内部的变量

在函数内部返回另一个函数,返回的函数中将函数内的变量返回

什么是原型和原型链

  • 原型:每个实例对象都有自己的原型,也就是构建自己的原型对象
  • 原型链:当查找某个属性的时候会先在对象本身查找,没有再从原型上找

什么是深拷贝和浅拷贝,如何实现?

  • 浅拷贝:将对象或数组赋值给新对象时,赋值引用关系,修改新对象原来对象也会跟着变
  • 深拷贝:将对象或数组赋值给新对象时,是创建一个新的对象,和之前的没有引用关系,修改新对象原来对象不会变。

事件循环机制(微任务、宏任务)

  • JS是单线程的
  • 先执行同步代码,然后执行微任务,再渲染dom,最后执行宏任务。
  • 微任务:Promise
  • 宏任务:setTimeout、setInterval

This指向

  • this指向的是调用者
  • 没有调用者的时候默认是window对象,有调用者的时候this指向调用者
  • 普通函数的this指向的是调用者,没有调用者默是window
  • 箭头函数的this指向的是函数作用域的对象

内存(垃圾)回收机制GC

  • JavaScript是自动的垃圾回收机制,会根据算法找出不再引用的变量或属性,Js会释放掉。
  • 当创建一个对象或数组时会占用内存,不再使用时需要置为null

call, alpay,bind的区别

  • 作用相同,都是可以改变this指向
  • call和appaly是直接执行该函数,bind方法执行后返回该函数,需要再多加一个()执行。
  • 第一个参数都是this的指向对象, 第二个参数call和bind是挨个放进去,apply是数组

ES6

let const、var的区别

  • let: 只在作用域内可访问,可以修改
  • const:只在作用域内可访问,不可修改
  • var:全局作用域,可修改

Promise

  • Promise是为了解决链式调用的问题
  • 通过new Promise可以创建一个Promise对象, Promise有三种状态,请求中pending,请求成功resoved, 请求失败rejected
  • 在Promise中可以执行异步请求,使用resolve返回正常的值,reject返回错误的值, 通过then方法接收返回的值,通过catch方法捕捉错误内容
  • Promise.all方法可以同时执行多个异步请求,全部请求成功才会返回成功,其中有一个失败就会返回失败

Class类

  • Class是面向对象语法的实现
  • 构造函数:通过constructor构造函数进行构建对象的属性
  • 继承:通过extends关键字实现继承,通过super执行父类的构造函数并传递初始化参数

async await

  • 将异步函数改为同步写法
  • 使用async在函数名前声明,在函数内的异步方法前添加await

Es6常用方法

  • map、find、filter、reduce、every
  • 箭头函数,扩展运算法、模板字符串
  • Object.keys、Object.values

Vue

MVVM的理解

Model 模型, View 视图,ViewModel 视图模型

v-show和v-if的区别

v-show控制样式display隐藏显示

v-if控制是否渲染dom

for循环中key的作用

循环项增加指针,提高性能

watch、computed、methods区别

watch是监控某个数据的变量,当数据变化的时候执行其他的操作。 **immediate**添加属性可以在第一次调用时执行,deep进行深度监听

computed 是根据依赖的数据变化,让本身的数据发生变化

methods 是定义的方法,可以在执行的时机执行

Vue生命周期

  • beforeCreate 不能访问this

  • created 有this

    • 请求数据 如果有涉及dom的操作要放到nextTick中
  • beforeMounte

  • mounted

    • 操作dom
  • beforeUpdate

  • updated

  • beforeDestory (Vue3:unMounte)

  • Destoryed (Vue3:unMounted)

  • deactivated(keep-alive离开)

  • activated(keep-alive进入)

Vuex状态管理

  • 五个模块:state、getters, mutions, actions, mudules
  • 在actions中执行异步操作,然后通过commit执行mution,在mution中修改state的值,在页面中通过computed计算属性引用。
  • mapGetter、mapActions

改了数据页面没有变

由于JavaScript的限制,Vue不能检测数组和对象属性的删除和增加

使用官方提供的$set方法

Keep-alive

用来做组件缓存,当切面需要频繁切换的时候不想让内容每次都加载恢复到初始的样子,可以使用keep-alive进行缓存

使用keey-alive包裹路由组件,通过exclude排除页面,include白名单包含要缓存的页面。

next-Tick

dom更新完毕后执行

原理:首先使用Promise, 如果不支持Promise使用MutationObserver,都不行最后会使用setTimout

data为什么是函数

通过函数返回一个新的对象,等于每个组件都是单独的data对象,如果data是对象的话所有组件都会同步。

Vue2、Vue3响应式原理

Vue2

通过Object.definePrototype

Vue3

通过proxy

Vue父子组件通信

  • 父->子:Props
  • 子->父:$emit
  • 子->父:$parents
  • 父->子:$ref

Vue非父子组件通信

  • 桥接 子1->父->子2
  • eventBus
  • 深层:父provide/子inject(Vue2.2.0)
  • Vuex

Vue-router路由模式和实现原理

  • hash模式 window.onhashchange
  • history模式 history.pushState 需要后端配合将请求指向index.html,否则会404

Vue-router路由生命周期

路由钩子

全局钩子:进入之前:beforeEach、解析中:beforeResolve、进入之后:afterEach、

单个路由:beforeEnter

组件路由:进入之前:beforeRouteEnter、更新:beforeRouteUpdate、离开之前:beforeRouteLeave

执行顺序

  • 上一个组件离开->先全局 -> 再单独 -> 最后组件内
  • 组件离开之前 -> 全局进入之前 -> 单独路由进入之前 -> 组件内进入之前 -> 全局解析中 -> 全局进入后 -> 组件内进入后
  1. beforeRouteLeave - 组件离开
  2. beforeEach - 全局进入
  3. beforeEnter - 单独路由进入
  4. beforeRouteEnter - 组件进入
  5. beforeResolve - 全局解析
  6. afterEach - 全局进入后
  7. beforeRouteEnter - 组件进入后

Vue虚拟DOM

虚拟dom组成结构为标签名称tagName、标签属性props、标签子元素children

let element={
    tagName:'ul',//节点标签名
    props:{  //dom的属性,用一个对象存储键值对
        id:'list'
    },
    children:[//该节点的子节点
        {tagName:'li',props:{class:'item'},children:['aa']},
        {tagName:'li',props:{class:'item'},children:['bb']},
        {tagName:'li',props:{class:'item'},children:['cc']}
    ]
} 

Vue3

Vue3有哪些更新

  • componstion Api-组合式API
  • Object.defineProperty改为proxy
  • 对Ts更好的支持
  • framents-根组件支持多节点
  • Teleport-可以将dom移动到指定位置
  • script setup

Vue3 Componstion Api

更方便逻辑重用,逻辑更清晰,相同功能逻辑放到同一个hook中

reactive和ref有什么不同?

reacive是一组数据,传入对象,使用的时候也不需要通过.value

ref适合基础数据,使用的时候需要通过.value

说一下Vue3中的tree shaking特性

去除掉没有使用过的代码,vue3中会检测在项目中使用了那些功能,没有使用过的将不会打包。

Vue2和Vue3中diff算法的区别

Vue2是全量更新,Vue3中是静态标记+非全量更新

修改当前组件中的某个属性会更新整个组件,Vue3中只会修改对应的dom

TypeScript

  • ts有哪些数据类型

    • 基础类型

      Boolean、Number、String、Undefined、Null、Any

  • ts中如何定义一个接口

    通过interface定义接口

  • 枚举-enums

    通过enum关键字定义枚举

  • 元祖

    本质上是数组,唯一不同的是可以单独指定数组内元素类型

  • 接口-interface

    定义一组数据的类型

  • 类型别名-type

    通过type关键字定义类型的别名

  • interface和type的区别

    相同点:首相相同点都是用来定义某种类型接口,都支持继承

    不同点:

    重复声明:interface可以重复定义,会自动合并,type不可以重复定义

    继承方式:interface通过extends实现,type通过 & 实现继承

性能优化

前端性能优化主要是有两个大的方向,资源和请求。

  • 资源

    1. 静态资源使用CDN
    2. 使用字体图标
    3. 压缩文件
    4. 图片延迟加载
    5. 图片使用webp格式
  • 请求

    1. 减少http请求
    2. 服务端渲染
    3. http缓存