面试总结

85 阅读19分钟

工程化

工程化是一种思想,而不是某种技术。其主要目的为了提高效率和降低成本,即提高开发过程中的开发效率,减少不必要的重复工作时间等。 前端工程化应该从四个方面进行考虑:组件化,模块化,规范化,自动化

模块化

模块化就是把一个大的文件,拆分成多个相互依赖的小文件,按一个个模块来划分。

js的模块化方案:

  • ADM
  • CommonJS
  • ES6 Module

css的模块化:

在less,sass,stylus等预处理器import/Mini的特性支持下实现

组件化

页面上所有的东西都可以看成组件,页面是个大型组件,可以拆成若干个中型组件,然后中型组件还可以再拆,拆成若干个小型组件

  • 组件化≠模块化。模块化只是在文件层面上,对代码和资源的拆分;组件化是在设计层面上,对于UI的拆分
  • 目前市场上的组件化的框架,主要的有Vue,React

规范化

在项目规划初期制定的好坏对于后期的开发有一定影响。包括的规范有

  • 目录结构的制定
  • 编码规范
  • 前后端接口规范
  • 文档规范
  • 组件管理
  • Git分支管理
  • Commit描述规范
  • 定期codeReview
  • 视觉图标规范

自动化

简单重复的工作交给机器来做,自动化也就是有很多自动化工具代替我们来完成。 持续集成、自动化构建、自动化部署、自动化测试等等

TCP/IP模型

TCP/IP模型是互联网的基础,它是一系列网络协议的总称。这些协议可以划分为四层,分别为链路层、网络层、传输层和应用层。

  • 链路层:负责封装和解封装IP报文,发送和接受ARP/RARP报文等。
  • 网络层:负责路由以及把分组报文发送给目标网络或主机。
  • 传输层:负责对报文进行分组和重组,并以TCP或UDP协议格式封装报文。
  • 应用层:负责向用户提供应用程序,比如HTTP、FTP、Telnet、DNS、SMTP等

UDP 用户数据报协议

UDP只能提供不可靠的交付,但具有端口功能和差错检测功能

有端口,在运输层就能进行服用和分用

UDP的特点:

  • UDP是面向无连接的,即发送数据之前不需要建立连接,因此减少了开销和发送数据之前的时延
  • UDP尽最大努力交付,即不保证可靠交付,但也不使用流量控制和拥塞控制,因此主机不需要维持具有许多参数,复杂的连接状态表。
  • 由于UDP没有拥塞控制,因此网络出现的拥塞不会源主机的发送速率降低。
  • UDP是面向报文的,即UDP对应用程序交下来的报文不再划分为若干个分组来发送,也不把收到的若干个报文合并后再交付给应用程序
  • UDP支持一对一,一对多,多对一和多对多的交互通信
  • 用户数据报只有8个字节的首部开销,比TCP的20个字节首部要短很多。

缺点:

  • 不可靠,但是可通过提高可靠性传输措施如:采用向前纠错或者重传已丢失的报文。
  • 由于没有拥塞控制功能,可能会引起网络发生严重的拥塞控制。

TCP传输控制协议

TCP是TCP/IP体系中面向连接的运输层协议,提供全双工的和可靠交付的服务,在运输层使用了流量控制和拥塞控制机制。

TCP特点:

  • 面向连接,建立连接的目的是通信双方为接下来的数据传送做好准备,初始化各种状态变量,分配缓存资源,数据传送完毕,必须释放已建立的连接。
  • 只支持一对一通信
  • 提高可靠交付的服务,TCP发送方每发送一个报文段,都会设置一个计时器,超过时间没有收到确认,则重传报文。
  • 提高全双工通信,即允许通信双方的应用进程在任何时候都能发送数据。,采用延迟确认机制,以提高TCP的传输速率。同时还采用滑动窗口协议,发送窗口的大小单位是字节,而不是分组数。
  • 面向字节流。

TCP的三次握手发送第三个报文是为了防止已失效的连接请求报文段突然传送到服务端,因而产生错误。(该报文段是因为在某些网络节点滞留太长时间,导致客户端又重送一个报文,与服务器建立连接)

浏览器

1647920034(1).png

浏览器的组成

  • 用户界面 - 包括地址栏、前进/后退按钮、书签菜单等。除了浏览器主窗口显示的你请求的页面外,其他显示的各个部分都属于用户界面。
  • 浏览器引擎 - 在用户界面和渲染引擎之间传送指令。
  • 渲染引擎 - 负责显示请求的内容。如果请求的内容是 HTML,它就负责解析 HTML 和 CSS 内容,并将解析后的内容显示在屏幕上。

1647920190(1).png

  • 网络 - 用于网络调用,比如 HTTP 请求。其接口与平台无关,并为所有平台提供底层实现。
  • 用户界面后端 - 用于绘制基本的窗口小部件,比如组合框和窗口。其公开了与平台无关的通用接口,而在底层使用操作系统的用户界面方法。
  • JavaScript 解释器。用于解析和执行 JavaScript 代码,比如chrome的javascript解释器是V8。
  • 数据存储。这是持久层。浏览器需要在硬盘上保存各种数据,例如 Cookie。新的 HTML 规范 (HTML5)定义了“网络数据库”,这是一个完整(但是轻便)的浏览器内数据库

输入url

查看浏览器缓存,看是否有缓存,如果有缓存,继续查看缓存是否过期,如果没有过期,直接返回缓存页面,如果没有缓存或者缓存过期,发送一个请求。

  • 浏览器解析url地址,获取协议、主机名、端口号和路径。
  • 获取主机ip地址过程 (1)浏览器缓存 (2)主机缓存 (3)hosts文件 (4)路由器缓存 (5)DNS缓存 (6)DNS递归查询
  • 浏览器发起和服务器的TCP连接,执行三次握手建立连接
  • 三次握手连接后,浏览器发送一个http请求
  • 服务器收到请求,转到相关的服务程序,期间可能需要连接并操作数据库。
  • 服务器看是否需要缓存,服务器处理完请求,发出一个响应。
  • 服务器并根据请求头包含信息决定是否需要关闭TCP连接,如需关闭,则需要四次挥手过程
  • 浏览器对接收到的响应报文进行解析
  • 构建DOM树和css规则树,构建render树,render树进行绘制布局,渲染render树
  • 处理嵌入的其他资源如css文件、js文件、图片文件、音视频等文件,重复上述过程。

ios与安卓的兼容性问题

  1. 时间格式问题 JavaScript中的Date对象在Safari与IOS中,如果 Date.parse(new Date('2018-03-30 12:00:00')) 结果是NaN 需要先把时间格式化为YYYY/MM/DD,不能是YYYY-MM-DD

  2. 在h5的静态页面会出现一个非常难受的问题,就是当页面出现多个input输入框的时候,导致最下面一个输入框,点击的时候弹出的键盘会遮挡输入框。用户根本不知道自己输入的是什么,对用户的体验非常不友好。解决方案:

就是选中当前的DOM元素,让他出现在可视区域的顶部或者底部。代码如下:

document.querySelector('#inputId').scrollIntoView();

  1. 设置overflow-y时滚动区域不流畅问题

-webkit-overflow-scrolling:touch

但是该属性在position:fixed下,会导致fixed固定定位失效,元素跟着一起上下滚动,也会导致z-index失效,解决方案是调整布局。

前端性能优化

减少http请求

  • 图片的处理,可以采用雪碧图,图片采用base64编码,使用字体图标代替图片,
  • 减少重定向,
  • 合理使用缓存,浏览器缓存
  • 避免使用css的@import,因为它会造成额外的请求
  • 避免使用空的src和href,a标签设置空的href,会重定向到当前页面的地址,form设置空的method,会提交表单到当前页面的地址

压缩资源

静态资源html,css,js的压缩,图片压缩

优化网络

  • 使用CDN分发网络,提高响应速度
  • 使用DNS预解析
  • 持久化连接,使用keep-alive或者persistent来建立持久连接,降低了延时和连接建立的开销

优化资源加载

  • 资源加载位置,优化资源加载位置,更改资源加载时机,css尽量放在head,js尽量放在body底部,body尽量不写style标签和script标签。

  • 资源加载时机 1) 异步script标签 defer:异步加载,在html解析完成后执行。defer的实际效果与将代码放在body底部类似
    async:异步加载,加载完成后立即执行 2) 模块按需加载 在SPA等业务比较复杂的系统中,需要根据路由来加载当前页面所需要的业务模块 按需加载,是一种很好的优化网页或应用的方式。这种方式实际上是先把代码在一些逻辑断点处分离开,然后在一些代码块中完成某些操作后,立即引用另外一些新的代码块。这样加快了应用的初始加载速度,减轻了它的总体体积

    webpack提供了两类技术,优先选择的方式是使用符合ECMAScript提案的import语法,第二种就是使用webpack特定的require.ensure

3)使用资源预加载和懒加载

减少重绘和回流

使用性能好的API

  • 使用requestAnimationFrame来替代setTimeout和setInterval
  • 使用IntersectionObserver来实现图片可视区域的懒加载

webpack性能优化

  • 打包公共代码 通过optimization.splitChunks和optimization.runtimeChunk,启动代码分割配置
  • 动态导入和按需加载 webpack提供了两种技术通过模块内联函数用来分离代码,优先选择的方式是ECMAScript提案的import()语法,第二种则是使用webpack特定的require.ensure
  • tree-sharking删除无用的代码 js的tree shaking主要通过uglifyjs来完成,css的tree shaking通过purify css来实现
  • 长缓存优化 使用Name而不是id

每个 module.id 会基于默认的解析顺序(resolve order)进行增量。也就是说,当解析顺序发生变化,ID 也会随之改变

下面来使用两个插件解决这个问题。第一个插件是 NamedModulesPlugin,将使用模块的路径,而不是数字标识符。虽然此插件有助于在开发过程中输出结果的可读性,然而执行时间会长一些。第二个选择是使用 HashedModuleIdsPlugin,推荐用于生产环境构建

  • 公共代码内联 使用html-webpack-inline-chunk-plugin插件将manifest.js内联到html文件中

react组件性能优化

类组件善用shouldComponentUpdate,其默认返回值为true时,即“无条件 re-render”,只要父组件更新,子组件将无条件更新 合理使用PureComponet+Immutable.js,PureComponent已经默认在shouldComponent中对组件更新前后的props进行浅比较,根据对比结果决定是否更新。 React.memo和useMemo

语义化

html 语义化:语义化是指根据内容的结构化(内容语义化),选择合适的标签(代码语义化。优点是有利于seo,增强了代码可读性,使结构更加清晰。

meta

meta标签是HTML语言HEAD区的一个辅助性标签。常用于定义页面的说明,关键字,最后修改日期,和其它的元数据。这些元数据将服务于浏览器(如何布局或重载页面),搜索引擎和其它网络服务。 常见用法:

  1. 声明网页字符编码:
<meta charset="UTF-8">
  1. 禁止缩放
<meta name=”viewport” content=”initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no”/>
  1. 自动刷新网页 meta http-equiv=”refresh”可以指定浏览器延迟一段时间自动刷新页面
<meta http-equiv=”refresh” content=”5″ />
  1. 自动重定向
<meta http-equiv=”refresh” content=”5;url=’https://www.gxlcms.com’” />

5.禁止浏览器缓存

当我们在本地测试网页的时候,没有及时更新新内容,可能就是有浏览器缓存

<meta http-equiv="expires" content="0">
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">

6.禁止百度转码

<meta http-equiv="Cache-Control" content="no-siteapp"/>

7.在移动开发当中,屏蔽数字当作电话号码的代码

<meta content=”telephone=no” name=”format-detection” />

两种方法可以启用 CSP。一种是通过 HTTP 头信息的 Content-Security-Policy的字段。 另一种是通过网页的标签。

<meta http-equiv="Content-Security-Policy" content="script-src 'self'; object-src 'none'; style-src cdn.example.org third-party.org; child-src https:">

参考链接:www.gxlcms.com/htmldaima-3…

scr vs href

  • src: 表示对资源的引用,它指向的内容会嵌入到当前标签所在的位置。将其指向的资源下载并应⽤到⽂档内,如请求js脚本。当浏览器解析到该元素时,会暂停其他资源的下载和处理,直到将该资源加载、编译、执⾏完毕,所以⼀般js脚本会放在页面底部。

  • href: 表示超文本引用,它指向一些网络资源,建立和当前元素或本文档的链接关系。当浏览器识别到它他指向的⽂件时,就会并⾏下载资源,不会停⽌对当前⽂档的处理。 常用在a、link等标签上

async vs defer

defer 和 async属性都是去异步加载外部的JS脚本文件,都不会阻塞页面的解析。其区别如下: 1)执行顺序,多个带async属性的标签,不能保证加载的顺序;多个带defer属性的标签,按照加载顺序执行 2)是否并行执行脚本,async属性,表示后续文档的加载和执行与js脚本的加载和执行是并行进行的,即异步执行;defer属性,加载后续文档的过程和js脚本的加载(即仅加载不执行)是并行进行的(异步),但是js脚本的执行需要等到文档所有元素解析完成之后,DOMContentLoaded事件触发执行之前

当初始的 HTML 文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发,而无需等待样式表、图像和子框架的完全加载。在IE8中,可以使用readystatechange事件来检测DOM文档是否加载完毕。

DomContentLoaded和load事件的区别 load事件:等到页面所有的资源(html、js、css、图片)等加载完成后才会执行 DomContentLoaded事件:Dom加载完就执行的

 img的srcset属性的作⽤

srcset属性用于设置不同屏幕密度下,img 会自动加载不同的图片。用法如下:

<img src="image-128.png" srcset="image-256.png 2x" /> 

行内元素有哪些?块级元素有哪些? 空(void)元素有那些?

  1. 行内元素有:a b span img input select strong
  • 设置宽高无效;
  • 可以设置水平方向的margin和padding属性,不能设置垂直方向的padding和margin;
  • 不会自动换行
  1. 块级元素有:div ul ol li dl dt dd h1 h2 h3 h4 h5 h6 p
  • 可以设置宽高;
  • 设置margin和padding都有效;
  • 可以自动换行;
  • 多个块状,默认排列从上到下。

空元素,即没有内容的HTML元素。空元素是在开始标签中关闭的,也就是空元素没有闭合标签:

  • 常见的有:<br><hr><img><input><link><meta>
  • 鲜见的有:<area><base><col><colgroup><command><embed><keygen><param><source><track><wbr>

浏览器是如何对 HTML5 的离线储存资源进行管理和加载?

  • 在线的情况下,浏览器发现 html 头部有 manifest 属性,它会请求 manifest 文件,如果是第一次访问页面 ,那么浏览器就会根据 manifest 文件的内容下载相应的资源并且进行离线存储。如果已经访问过页面并且资源已经进行离线存储了,那么浏览器就会使用离线的资源加载页面,然后浏览器会对比新的 manifest 文件与旧的 manifest 文件,如果文件没有发生改变,就不做任何操作,如果文件改变了,就会重新下载文件中的资源并进行离线存储。
  • 离线的情况下,浏览器会直接使用离线存储的资源

iframe 有那些优点和缺点?

iframe 元素会创建包含另外一个文档的内联框架(即行内框架)。

优点:

  • 用来加载速度较慢的内容(如广告)
  • 可以使脚本可以并行下载
  • 可以实现跨子域通信

缺点:

  • iframe 会阻塞主页面的 onload 事件
  • 无法被一些搜索引擎索识别
  • 会产生很多页面,不容易管理

隐藏元素的方法有哪些

  • display: none:渲染树不会包含该渲染对象,因此该元素不会在页面中占据位置,也不会响应绑定的监听事件。
  • visibility: hidden:元素在页面中仍占据空间,但是不会响应绑定的监听事件。
  • opacity: 0:将元素的透明度设置为 0,以此来实现元素的隐藏。元素在页面中仍然占据空间,并且能够响应元素绑定的监听事件。
  • position: absolute:通过使用绝对定位将元素移除可视区域内,以此来实现元素的隐藏。
  • z-index: 负值:来使其他元素遮盖住该元素,以此来实现隐藏。
  • clip/clip-path :使用元素裁剪的方法来实现元素的隐藏,这种方法下,元素仍在页面中占据位置,但是不会响应绑定的监听事件。
  • transform: scale(0,0) :将元素缩放为 0,来实现元素的隐藏。这种方法下,元素仍在页面中占据位置,但是不会响应绑定的监听事件。

伪元素和伪类的区别和作用?

  • 伪元素(双冒号):在内容元素的前后插入额外的元素或样式,但是这些元素实际上并不在文档中生成。它们只在外部显示可见,但不会在文档的源代码中找到它们,因此,称为“伪”元素。。
  • 伪类(单冒号):将特殊的效果添加到特定选择器上。它是已有元素上添加类别的,不会产生新的元素。 伪类是通过在元素选择器上加⼊伪类改变元素状态,⽽伪元素通过对元素的操作进⾏对元素的改变。

为什么有时候⽤translate来改变位置⽽不是定位?

translate 是 transform 属性的⼀个值。改变transform或opacity不会触发浏览器重新布局(reflow)或重绘(repaint),只会触发复合(compositions)。⽽改变绝对定位会触发重新布局,进⽽触发重绘和复合。transform使浏览器为元素创建⼀个 GPU 图层,但改变绝对定位会使⽤到 CPU。 因此translate()更⾼效,可以缩短平滑动画的绘制时间。 ⽽translate改变位置时,元素依然会占据其原始空间,绝对定位就不会发⽣这种情况

如何用 Webpack 实现对 CSS 的处理

  • Webpack 中操作 CSS 需要使用的两个关键的 loader:css-loader 和 style-loader
  • css-loader:导入 CSS 模块,对 CSS 代码进行编译处理;
  • style-loader:创建style标签,把 CSS 内容写入标签

浮动元素引起的问题?

  • 父元素的高度无法被撑开,影响与父元素同级的元素

  • 与浮动元素同级的非浮动元素会跟随其后

  • 若浮动的元素不是第一个元素,则该元素之前的元素也要浮动,否则会影响页面的显示结构 清除浮动的方式如下:

  • 给父级div定义height属性

  • 最后一个浮动元素之后添加一个空的div标签,并添加clear:both样式

  • 包含浮动元素的父级标签添加overflow:hidden或者overflow:auto

  • 使用 :after 伪元素。由于IE6-7不支持 :after,使用 zoom:1 触发 hasLayout**

.clear::after{ content:''; display: block; clear:both;}

clear属性只有块级元素才有效的,而::after等伪元素默认都是内联水平,这就是借助伪元素清除浮动影响时需要设置display属性值的原因。

BFC

块格式化上下文(Block Formatting Context,BFC)是Web页面的可视化CSS渲染的一部分,是布局过程中生成块级盒子的区域,也是浮动元素与其他元素的交互限定区域。 创建BFC的条件:

  • 根元素:body;

  • 元素设置浮动:float 除 none 以外的值;

  • 元素设置绝对定位:position (absolute、fixed);

  • display 值为:inline-block、table-cell、table-caption、flex等;

  • overflow 值为:hidden、auto、scroll; BFC的特点:

  • 垂直方向上,自上而下排列,和文档流的排列方式一致。

  • 在BFC中上下相邻的两个容器的margin会重叠

  • 计算BFC的高度时,需要计算浮动元素的高度

  • BFC区域不会与浮动的容器发生重叠

  • BFC是独立的容器,容器内部元素不会影响外部元素

  • 每个元素的左margin值和容器的左border相接触 BFC的作用:

  • 解决margin的重叠问题:由于BFC是一个独立的区域,内部的元素和外部的元素互不影响,将两个元素变为两个BFC,就解决了margin重叠的问题。

  • 解决高度塌陷的问题:在对子元素设置浮动后,父元素会发生高度塌陷,也就是父元素的高度变为0。解决这个问题,只需要把父元素变成一个BFC。常用的办法是给父元素设置overflow:hidden

  • 创建自适应两栏布局:可以用来创建自适应两栏布局:左边的宽度固定,右边的宽度自适应。