面试整理之原理问题

最近面试问到的原理问题还是挺多的,大致整理下

关于vue的

1.MVVM双向数据绑定原理

 所谓MVVM数据双向绑定,即主要是:数据变化更新视图,视图变化更新数据。

视图变化更新数据我们可以通过事件监听的方式来实现,关键点在于数据变化如何更新视图.Vue内部通过Object.defineProperty方法属性拦截的方式,把data对象里每个数据的读写转化成getter/setter,当数据变化时通知视图更新。

实现方法: 首先使用Object.defineProperty方法使data中的数据变化变成可监测, 然后在数据被读或写的时候通知那些依赖该数据的视图更新了,为了方便,我们需要先将所有依赖收集起来,一旦数据发生变化,就统一通知更新。其实,这就是典型的“发布订阅者”模式,数据变化为“发布者”,依赖对象为“订阅者”。

创建一个依赖收集容器,也就是消息订阅器Dep,用来容纳所有的“订阅者”。订阅器Dep主要负责收集订阅者,然后当数据变化的时候后执行对应订阅者的更新函数。

 

2.vuex实现原理

vuex 整体思想诞生于 flux,可其的实现方式完完全全的使用了 vue 自身的响应式设计,依赖监听、依赖收集都属于 vue 对对象 Property set get 方法的代理劫持。最后一句话结束 vuex 工作原理,vuex 中的 store 本质就是没有 template 的隐藏着的 vue 组件;

解析:vuex的原理其实非常简单,它为什么能实现所有的组件共享同一份数据? 因为vuex生成了一个store实例,并且把这个实例挂在了所有的组件上,所有的组件引用的都是同一个store实例。 store实例上有数据,有方法,方法改变的都是store实例上的数据。由于其他组件引用的是同样的实例,所以一个组件改变了store上的数据, 导致另一个组件上的数据也会改变,就像是一个对象的引用。

3.vue-router实现原理

 

其他

4.promise理解

Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理

有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。

优点: 可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise对象提供统一的接口,使得控制异步操作更加容易。

缺点: 无法取消Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。第三,当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。

API:  Promise.prototype.then(): 为 Promise 实例添加状态改变时的回调函数。then方法的第一个参数是resolved状态的回调函数,第二个参数(可选)是rejected状态的回调函数。可以使用链式写法, 

  Promise.prototype.catch(): 是.then(null, rejection).then(undefined, rejection)的别名,用于指定发生错误时的回调函数。

  Promise.prototype.finally(): 用于指定不管 Promise 对象最后状态如何,都会执行的操作。该方法是 ES2018 引入标准的。

  Promise.all(): 用于将多个 Promise 实例,包装成一个新的 Promise 实例,参数可以不是数组,但必须具有 Iterator 接口,且返回的每个成员都是 Promise 实例。

  Promise.race(): 

  Promise.any(): 方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例。只要参数实例有一个变成fulfilled状态,包装实例就会变成fulfilled状态

  Promise.resove():  将现有对象转为 Promise 对象

  Promise.reject():  Promise.reject(reason)方法也会返回一个新的 Promise 实例,该实例的状态为rejected

 

promise与settimeout执行顺序: then和settimeout执行顺序,即setTimeout(fn, 0)在下一轮“事件循环”开始时执行,Promise.then()在本轮“事件循环”结束时执行。因此then 函数先输出,settimeout后输出。

5.webpack理解

 

6.babel实现

 

7.JS作用域理解

 

8.JS原型链

 

9.JS继承

 

10.前端性能优化

 页面加载缓慢原因: 

  网络层面: 1.过多的HTTP请求  2.资源访问宽带小 3.网页元素(图片,视频,样式)太大 

 浏览器渲染层面: 1.渲染阻塞 JS阻塞与CSS阻塞  2.重复渲染  3.DNS解析

 服务端层面: 1.硬件配置低  2.服务器软件, 比如防火墙,内网策略等  3.未对NGINX这类web服务器进行配置优化  4.CPU占满,数据库未优化 5.包含了过多的分析工具

  代码部分: 1.未对代码进行打包,压缩,兼容性优化   2.未合并重复的请求,代码  3.没有良好的编码习惯  4.未加入async异步机制   5.未考虑页面加载,用户体验

 

页面优化处理: 

  1.减少HTTP请求, 合并请求,图片资源合并

  2.使用内容分发网络CDN  是用于分发传送内容的负载的服务器网络.从本质上讲,您网站的副本存储在多个地理位置不同的数据中心,以使用户可以更快,更可靠的         访问您的网络.除了购买一些CDN服务商的服务外,可以使用公共CDN网络上的资源

  3.避免空src和空href标签

  4.减少浏览器的重排reflow和重绘repaint, 使用vue减少操作DOM,减少不必要的DOM层级,使用class设计元素属性,不使用style设计属性

  5.CSS放在顶部,JS放在底部

  6.减少DNS查找,使用DNS预解析(NDS缓存)

  7.压缩资源 主要工具 webpack gulp

  8.避免3xx重定向,写完整请求路径,4xx请求错误 ,使用工具检查,使用路由规则

  9.尽量使用get请求,使用请求缓存

  10.去除不必要的cookie,压缩cookie大小,设置合适的过期时间

  11.使用浏览器缓存,localstorage sessionstorage

  12.缩短服务器响应时间

  13.使用优化工具: Google Page Speed

          JsPerf&Benchmark.js

11.浏览器输入URL到页面渲染的过程

1. 用户输入URL地址

2.浏览器解析URL 主机名

3. 浏览器将主机名转换成服务器ip地址(浏览器先查找本地DNS缓存列表,没有的话再向浏览器默认的DNS服务器发送查询请求 同时缓存)

4. 浏览器将端口号从URL中解析出来

5. 浏览器建立一条鱼目标web服务器的TCP连接(三次握手)

6. 浏览器向服务器发送一条HTTP请求报文

7. 服务器向浏览器返回一条HTTP响应报文

8. 关闭连接 浏览器解析文档

9. 如果文档中有资源 重复6 7 8动作, 直至资源全部加载完毕

 简洁版: 1.域名解析 --> 2.发起 TCP 的 3 次握手 --> 3.建立 TCP 连接后发起 http 请求 --> 4.服务器响应 http 请求,浏览器得到 html 代码 --> 5.浏览器解析 html 代码,并请求 html 代码中的资源(如 js、css、图片等) --> 6.浏览器对页面进行渲染呈现给用户

12.TCP三次握手

CP 协议是面向连接的通信协议,即在传输数据前先在发送端和接收端建立逻辑连接,然后再传输数据,它提供了两台计算机之间可靠无差错的数据传输。

在 TCP 连接中必须要明确客户端与服务器端,由客户端向服务端发出连接请求,每次连接的创建都需要经过“三次握手”

第一次握手,客户端向服务器端发送一个带 SYN 标志的数据包,等待服务器确认

第二次握手,服务器端向客户端回传一个带有 SYN/ACK 标志的数据包,通知客户端收到了连接请求

第三次握手,客户端再次向服务器端回传一个带 ACK 标志的数据包,确认连接,“握手”结束。

 

12.2 TCP四次挥手

1、客户端向服务器发送一个断开连接的请求(不早了,我该走了);

2、服务器接到请求后发送确认收到请求的信号(知道了);

3、服务器向客户端发送断开通知(我也该走了);

4、客户端接到断开通知后断开连接并反馈一个确认信号(嗯,好的),服务器收到确认信号后断开连接;

解析:

第一次挥手:主动关闭方发送一个 FIN,用来关闭主动方到被动关闭方的数据传送,也就是主动关闭方告诉被动关闭方:我已经不会再给你发数据了(当然,在 fin 包之前发送出去的数据,如果没有收到对应的 ack 确认报文,主动关闭方依然会重发这些数据),但是,此时主动关闭方还可 以接受数据。

第二次挥手:被动关闭方收到 FIN 包后,发送一个 ACK 给对方,确认序号为收到序号+1(与 SYN 相同,一个 FIN 占用一个序号)。

第三次挥手:被动关闭方发送一个 FIN,用来关闭被动关闭方到主动关闭方的数据传送,也就是告诉主动关闭方,我的数据也发送完了,不会再给你发数据了。

第四次挥手:主动关闭方收到 FIN 后,发送一个 ACK 给被动关闭方,确认序号为收到序号+1,至此,完成四次挥手。

13.跨域问题解决

 1.CORS 在vue项目中前端不需要做什么处理,后端设置Access-Control-Allow-Origin请求头

2.chrome浏览器支持可跨域的设置,根据网上的配置方法配置

3.vue.config.js文件中配置代理  

module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: '<url>',  // 跨域的地址
        ws: true,
        changeOrigin: true,
        pathRewrite: {'^/api': '/'}
      }
    }
  }
}
 

14.浏览器缓存策略

 浏览器的缓存规则是在 http 协议头和 html 页面的 meta 标签中定义的。主要分为两部分:强缓存和协商缓存。
强缓存是指缓存的副本在有效期内,浏览器直接获取这个副本并渲染。
强缓存主要涉及的 http 协议报头有:Expires,cache-control。

<meta http-equiv="Cache-Control" content="max-age=7200" /> // content: no-cache||no-store||max-age
<meta http-equiv="Expires" content="Mon, 20 Jul 2013 23:00:00 GMT" /> // 过期时间

协商缓存是在强缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程。

协商缓存的过程:浏览器发起 http 请求,浏览器缓存返回缓存标识(请求的缓存结果失效),浏览器携带该资源的缓存标识,向服务器发起 http 请求,如果服务器返回 304 和 not modified,浏览器向浏览器缓存获取该请求的缓存结果,浏览器环迅返回该请求结果。如果服务器返回 200 和请求结果(该资源更新了,重新返回请求结果),浏览器将该请求结果和缓存标识存入浏览器缓存中。

协商缓存主要涉及的 http 协议报头有:Last-Modified 和 ETag。

15.前端工程化

1.前端工程化概念: 前端项目越来越大,引用资源越来越多.为了提高效率和降低成本,即提高开发过程中的开发效率,减少不必要的重复工作时间,前端工程化变得越来越必要

2.前端工程化主要从四个方面进行: 前端模块化,前端组件化,前端规范化,前端自动化

前端模块化: 模块化就是将一个大文件拆分成相互依赖的小文件,再进行统一的拼装和加载.JS,CSS,引入资源的模块化

      主要使用打包工具:webpack,parcel,rollup

前端组件化: 组件是从UI拆分下来的每个包含模板(HTML)+样式(CSS)+逻辑(JS)功能完备的结构单元

      使用组件可以使项目开发更高效灵活

      主要组件化框架: vue,react,angular  微信小程序

前端规范化: 规范化其实是工程化中很重要的一个部分,项目初期规范制定的好坏会直接影响到后期的开发质量。

      主要规范: 编码规范 eslint stylelint, 接口规范, Git开发规范, 命名规范, 组件管理

前端自动化: 任何简单重复的工作都应该使用自动化工具来完成

      主要自动化: 自动构建项目 gulp; 

      自动化测试: 使用asset和chai进行单元测试; 使用Istanbul进行覆盖率测试; 使用benchmark进行性能测试; 使用jest进行UI测试

      自动部署项目 pm2

16.提高首屏加载速度

  1. 使用CDN资源,减小服务器带宽压力
  2. 路由懒加载
  3. 将一些静态js css放到其他地方(如OSS),减小服务器压力
  4. 按需加载三方资源,如iview,建议按需引入iview中的组件
  5. 使用nginx开启gzip减小网络传输的流量大小
  6. 若首屏为登录页,可以做成多入口,登录页单独分离为一个入口
  7. 使用uglifyjs-webpack-plugin插件代替webpack自带UglifyJsPlugin插件
posted @ 2020-03-02 10:29  潇湘羽西  阅读(385)  评论(0编辑  收藏  举报