前端面试题总结

135 阅读14分钟

js 和 DOM API

  • js数类型

    Boolean Number String null undefined Symbol Object

  • 闭包

    全局作用域和函数作用域,闭包是在函数作用域内定义函数,并返回该函数。该函数内用到了函数作用域内定义的变量或函数。可以用来封装私有数据,缺点是使用不当会导致内存泄漏

  • es5 继承的几种方法,那种最好

    • 拷贝继承,通过 for in 将父类的原型成员赋给子类的原型。简单直接,无法使用 instanceof
    • 原型继承(实现有很多中,这里只说原理),将父类的原型赋给一个函数,然后将该函数的实例作为子类的原型。可以使用 instanceof。
  • 原型和原型链,判断 a 是不是 B 的实例

    a instanceof B,instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上

  • es6 的 class

    class 是原型继承的语法糖,拥有 constructor 构造函数、super 调用父类方法、extends 实现继承。class 中的方法不可遍历,constructor 必须定义(默认是空函数),必须通过 new 构造实例(否则报错),class 定义不存在变量提升(hoist,必须先定义再使用)。

    es5 的继承是先创建子类的 this,然后将父类的特权成员添加到 this 上。es6 的 class 是先创建父类的 this,然后使用子类的构造函数修改 this。所以子类的构造函数必须首先调用 super函数,用来获取到父类的 this。

  • Promise 细节

    promise 实例有三种状态(待定 pending、已决议 fulfilled、已拒绝 rejected),其中已决议和已拒绝可以统称为 settled。原型上的 then 方法用来注册已决议和已拒绝两种情况的回调函数。

    then 方法返回一个新的 Promise 实例,新 Promise 的状态由 then 中回调函数的返回值确定。返回特定值、undefined、抛错、非待定状态的 Promise、待定状态的 Promise 都会影响新 Promise 实例的状态。

  • es6+ 的新特新有哪些

    • let 和 const
    • 变量解构语法
    • Symbol、Set、Map、Proxy、Reflect、Promise
    • Generator 函数和 Iterator
    • class
    • esm
  • let const var 的区别

    变量申明方式,let 和 const 存在块作用域,var 不存在块作用域。const 声明的变量不能修改。let 声明存在暂时性死区问题

  • 数组去重方法

    • [...new Set(arr)]、Array.from(new Set(arr))
    • for 循环判断(indexOf 判断是否存在于新数组中、将值作为对象属性,判断对象属性是否已村存在)
  • 事件委托

    DOM 事件具有捕获和冒泡阶段(并不是所有事件都会冒泡),在 Document 上监听事件,通过 target 属性判断触发事件的元素。

  • 获取 DOM 的方法

    • window[id]
    • document.all
    • document.getElementById、document.getElementsByTagName、document.getElementsByClassName、document.getElementsByName
    • document.querySelector、document.querySelectorAll
  • 浏览器捕获全局异常的方法

    • window.onerror / window.addEventListener('error')
    • try catch
    • window.addEventListener('unhandledrejection')

vue

  • mvvm 模式

    mvvm 是一种架构模式,model 是数据层、view 是视图层、viewModel 是视图引擎层和业务逻辑实现层。m 和 v 没有直接联系,vm 通过和 v 的双向绑定将 m 和 v 联系起来。v 中触发绑定事件,vm 执行事件处理函数,改变 m。m 的改变会影响到 vm 更新 v。mvvm 的核心思想是将视图的开发和业务逻辑开发分开(和 html、js 分开开发有什么区别?)。优点是视图和业务逻辑分开,方便测试业务逻辑。

  • 数据劫持实现原理

    vue 数据劫持表现在,对数据的修改能触发副作用函数执行。vue2 使用 Object.definedProperty 监控对象属性的 get 和 set 操作。vue3 使用 Proxy 对象,代理对数据的操作。区别是 vue2 只能检测到对已有属性的修改,新增和删除属性没法感知,需要使用辅助函数 $set$delete

  • created 和 beforeMount 区别

    created 在 vue 组件在创建时执行,beforeMount 在组件挂载时执行。

  • vue2 和 vue3 双向绑定的区别(v-model 语法的区别)

    vue2 中的双向绑定 v-model 是 :value 和 @input 的语法糖,只能绑定一个属性。vue2 中新增的 .sync 参数用来绑定多个属性,也是 :prop 和 @update:prop 的语法糖。vue3 中将两种绑定方式统一为 v-model:prop,是 :modelValue 和 @update:modelValue 的语法糖。可以绑定多个属性

  • vue2 和 vue3 watch 的区别

    vue2 中 watch 可以侦听组件上的响应数据、handler、上述任意值的数组。选项有immediate、deep vue3 中 watch 可以侦听 Ref、getter、reactive 对象、上述任意值的数组。选项有 immediate、deep、flush。vue3 的响应系统独立于框架,可以单独使用。

vuex

  • 什么是 vuex,优势和劣势

    vuex 是 vue 应用的状态管理器。用来存储应用中大部分状态,vuex 中的状态是响应式的,使用 commit 修改状态。优势是可以全局共享数据和方法。劣势是不能持久存储状态

  • 页面刷新后 state 丢失怎么解决

    state 中的数据是存在内存中的,刷新后 state 重新初始化。可以搭配 cookies 或者 localStorage 使用,在 state 改变时同步将数据持久化。刷新时使用 cookies 或者 localStorage 中的数据初始化 state

  • vuex 有哪些属性

    state、getters、mutations(commit触发)、actions(dispatch触发)、modules

css

  • 盒模型

    由内向外有 content、padding、border、margin 四个区域,对应有 content-box、padding-box、border-box 三种盒模型。通过 width、height 设置盒的大小。行内元素的高由 line-height 决定。

  • flex 布局

    flex 弹性盒模型,子元素可以弹性伸缩,拉伸用来占满未使用的空间,或者收缩用来防止父元素溢出。可以方便进行水平和垂直布局

    通过 flex-direction 定义主轴和交叉轴方向,flex-wrap 定义是否能换行。flex-flow 是两个属性的简写形式

    flex-basis 定义元素的空间大小,可以是确定值,百分比或 auto。为 auto 时,值为元素设置的 width 或元素内容尺寸。flex-grow 设置元素占用可用空间的比例。flex-shrink 设置元素收缩的比例。flex 是三个属性的简写形式

    align-items 定义元素在交叉轴对齐方式,justify-content 定义在主轴上的对其方式,align-content 定义多行中每行之间的空间分配方式。

  • 移动端响应式布局,如何根据设备大小布局,如何监听屏幕大小

    响应式布局可以结合媒体查询、百分比布局、flex布局方式实现。百分比布局衍生出 rem 布局和 vw vh 布局。js 中监听屏幕大小可使用 window 的 resize 事件。

浏览器和 Http

  • 浏览器的几种缓存机制

    • cookie

      cookie 作用域是 Domain 和 path,每次发送请求会带上作用域内的 cookie。服务端可以通过响应头 set-cookie 对客户端写入 cookie。通过 Expires和Max-Age 指定有效期。由于 cookie 经常用来保存身份信息,是 xss 和 csrf 的攻击目标。通过 HttpOnly 设置不能通过 js 访问。通过 SameSite 设置跨域访问权限,Strict 严格模式不能跨域访问,lex模式允许部分跨域请求访问,none模式下允许跨域访问。缺点是容量上限 4k,每次请求都会带上 cookie,占用带宽,不正确的设置容易导致用户 cookie 信息泄漏

    • localStorage

      作用域是域名,数据可以在同源窗口和标签中共享。存储的数据会长期保留,没有过期时间。大小是 5M 或更大,存储格式是字符串。

    • sessionStorage

      和 localStorage 类似,区别是不能在窗口和标签中共享,标签关闭后数据即清空。

  • 什么是跨域,怎么解决

    浏览器存在同源策略,当url中的协议 + 域名 + 端口三者一致时,就属于同源。非同源站点的限制是,不能读取和修改对方的 DOM;不能访问对方的 cookie、indexDB、localStorage;限制 ajax 请求。发起非同源请求时,即存在跨域问题。浏览器会拦截响应并在控制台报跨域错误。跨域的解决方法如下:

    • jsonp,原理是 script、img 标签能跨域。兼容性强,只能发送 get 请求。
    • cros,后端通过设置 Access-Control-Allow-Origin 等响应头,允许浏览器跨域请求。支持所有请求方式,使用时和同源请求一致。低版本 ie 不支持。
    • nginx 反向代理,同源策略是浏览器行为,通过 nginx 反向代理,将同源请求转发到需要跨域的接口。
    • iframe 可以加载跨域页面,宿主页面和跨域 iframe 通信受到限制,使用 postMessage 机制可以跨域跨页面通信。
  • 什么是 keep-alive

    http 请求采用请求-应答模式,一次请求创建一个 tcp 链接,完成断开链接。为了减少 tcp 的创建,提高网络性能,http1.0 增加了 keep-alive 模式(默认关闭), 当请求和响应头中包含 Connection: Keep-Alive 时,该 tcp 链接会在使用后被下一个请求复用(超时没有被复用的还是会被断开)。http1.1 时keep-alive 模式默认打开。

    keep-alive 模式下,tcp 被复用时判断响应数据已经接收完成的方法:

    • 通过 Conent-Length 判断接收到内容长度
    • 使用 Transfer-Encoding: chunk 开启分块编码,响应体中的数据会分块发送回浏览器。每块数据包含 16 进制的长度值和数据。最后一块长度为 0,表示响应数据发送完成
  • http 和 https 区别

    Http 协议是应用层协议,基于 TCP/IP 协议传输数据。Http 请求报文包括请求行、请求头、请求正文,响应报文包括状态行、响应头、响应正文。默认使用 80 端口。Http 请求是明文传输、数据完整性没有校验,容易被篡改、没有身份认证。Https 可以理解为 Http + SSL/TSL,用来解决 Http 的安全问题。Https 通过 ssl 证书来验证服务器,为通信进行加密。默认使用 443 端口。缺点是建立链接需要多次握手,ssl 的安全算法会消耗 cpu 资源,申请 ssl 证书需要钱。https 请求流程如下:

    • 客户端请求 https 链接
    • 服务端返回证书(含公钥)
    • 客户端验证证书有效性
    • 客户端产生随机对称密钥,使用服务端公钥将密钥加密
    • 客户端发送加密后的对称密钥
    • 服务端使用私钥解密密钥,之后通信都通过该对称密钥加密
  • GET 和 POST 区别

    • 都包含请求头和请求行,POST 多了请求正文(GET 也可以包含请求正文,但是不能保证服务端会处理)
    • GET 多用于查询请求,参数放在 url 中,POST 对用于提交,信息放在 body 中
    • GET 由于将数据放在 url 中,容易导致长度超出限制
    • ie 下会主动缓存 GET 请求
  • 常见http状态码

    • 101 Switching Protocols 在HTTP升级为WebSocket的时候,如果服务器同意变更,就会发送状态码 101。
    • 200 OK 成功状态码, 通常在响应体中放有数据。
    • 206 Partial Content HTTP 分块下载和断点续传
    • 301 Moved Permanently 即永久重定向
    • 302 Found 临时重定向,浏览器对301和302的处理方式不同,301时浏览器会做缓存优化
    • 304 Not Modified 当协商缓存命中时会返回这个状态码
    • 400 Bad Request
    • 403 Forbidden 服务器禁止访问
    • 404 Not Found 资源未找到
    • 405 Method Not Allowed 请求方法不被服务器端允许
    • 409 Conflict 多个请求发生了冲突
    • 500 Internal Server Error 服务器内部错误
    • 502 Bad Gateway 网关可以访问,反向代理的程序访问不了
    • 504 Gateway Timeout

cros 详细解释

浏览器将请求分为简单请求和非简单请求

简单请求满足的条件: 1. 方法为GET、POST、HEAD 2. 请求头范围 Accept、Accept-Language、Content-Language、Content-Type(有额外限制) 其他就是非简单请求

简单请求:

  1. 浏览器发起请求时, 在请求头中加入Origin字段,说明请求来自哪个源
  2. 服务端回应Access-Control-Allow-Origin字段,可以是 * 或者 某个origin
  3. 浏览器检测Origin和Access-Control-Allow-Origin是否匹配, 不匹配则拦截该响应

非简单请求:

  1. 浏览器首先发送预检请求,方法是options, 同时会加上Origin源地址和Host目标地址,还会加上Access-Control-Request-Method和Access-Control-Request-Headers列出跨域请求会用到哪个方法和哪些请求头
  2. 服务端响应头包含Access-Control-Allow-Origin表示允许跨域的域名、Access-Control-Allow-Methods允许跨域的方法列表、Access-Control-Allow-Headers允许跨域请求携带的请求头
  3. 浏览器检查请求是否满足响应头的条件,不满足直接报错,请求发不出去
  4. 满足预检请求的条件后,发起非简单请求,流程和简单请求的发起一致

浏览器缓存

  1. http1.0中使用 Expires: 过期时间,缺点是服务端和客户端时间设置不同。
  2. http1.1新增Cache-Control,缓存分强缓存,协商缓存,无缓存
  3. 缓存过期时间:
    • max-age=3600 代表响应返回后3600s内可以直接使用缓存
    • s-maxage=5000 是针对代理服务器的缓存时间,如果不考虑代理服务器的情况下,可以不用关注该字段
  4. public/private 是否允许代理服务器缓存该请求
  5. no-store 无缓存,即不允许客户端和服务器进行缓存
  6. no-cache 强制使用协商缓存
  7. max-age=0 可以使用缓存资源,但是每次都要验证缓存有效性,效果和设置no-cache一致
  8. 没有设置no-store和no-cache时,即开启强缓存
    • 验证max-age的有效性,没有过期则直接使用缓存资源,http的返回是200
    • 过期时,降级为协商缓存,向服务器发送 缓存tag,服务器通过该tag判断缓存是否过期,没有过期时返回304,过期时带上新资源的内容返回200。
      • 服务器响应Last-Modified,客户端通过If-Modified-Since发送该信息。
      • 服务端响应ETag,客户端通过If-None-Match发送该信息。
      • Last-Modified优点是性能好。缺点是只能精确到秒,对一秒内的变动识别不出来。编辑文件时,内容没有变动,会造成缓存失效。
      • ETag优点是能准确判断是否变更。缺点是性能差,每次变更需要计算内容的hash值。
  9. 浏览器缓存资源的位置:
    • Service Worker
    • Memory Cache
    • Disk Cache

网络安全和前端漏洞

  • xss(跨站脚本攻击),页面将恶意代码直接当作 html 片段插入到文档中,导致恶意代码被执行
    • 反射型是在 url 参数中加入 script 标签,用户点击后页面执行恶意脚本
    • 存储型是将 script 标签发布到留言区等,被存储在数据库。当用户浏览了该留言,就会执行恶意脚本 解决方法是过滤掉敏感字符[", ', script, iframe, onclick, onfocus];或者存储用户输入时进行转义
  • sql 注入 后端将用户的输入直接拼接到 sql 语句中,解决方法时过滤敏感字符
  • csrf(跨站请求伪造) 攻击者在 b 网站发起 a 网站的请求,利用用户在 a 网站的身份发送恶意请求。前提条件时用户登录了 a 网站,并生成本地 cookie。一般通过 img 标签模拟 get 请求,通过自动表单提交模拟 post 请求。解决方法如下:
    • 服务端验证请求的 referer,判断来源是否可信
    • 服务端下发 csrftoken,并在稍后的请求中一起发送回后端验证有效性
    • 设置 cookie 的 SameSite,严格模式下不能被跨站请求访问
  • 业务安全漏洞
    • 登录模块短信验证码接口,可能造成短信轰炸、验证码重放攻击。解决方式是,限制同一个账号的发送次数和频率;发送后的验证码要有失效机制;验证码可以设置为 6 位
    • 越权访问,对修改删除操作没有判断资源归属人,用户可以修改其他人的数据。解决方法是增加权限控制