前端技术总结一--原理篇
原理篇
1、 http1.0和2.0的区别
http1.0默认短连接(一次请求建议一次TCP连接,请求完就断开),但是增加了keep-alive关键字来由短链接变成长连接,就是请求报文里的字段指定Connection:keep-alive;支持GET、POST、 HEAD请求。
http1.1默认长连接(一次TCP连接可以多次请求),新增了5种请求类型(OPTIONS, PUT, DELETE, TRACE 和 CONNECT方法);请求头部增加了Host字段,在HTTP1.0中认为每台服务器都绑定一个唯一的ip地址,因此在URL中并没有传递主机名,但是随着虚拟机技术的发展,可能在一台物理机器上存在多个虚拟主机,并且他们共享了一个ip地址,http1.1中请求消息和响应消息都支持host头域;增加了100在内的一些状态响应码。
http2.0
u 多路复用,降低开销:(一次TCP连接可以处理多个请求), 一个连接里面并发处理请求,不像http1.1在一个tcp连接中各个请求是串行的;
u 解析基于二进制:解析错误少,更高效(HTTP/1.X解析基于文本);
u 压缩header:在1.0版本后增加了header头信息,2.0版本通过算法把header进行了压缩这样数据体积就更小,在网络上传输就更快。
2、 页面加载过程
(1),当发送一个URL请求时,不管这个URL是Web页面的URL还是Web页面上每个资源的URL,浏览器都会开启一个线程来处理这个请求,同时在远程DNS服务器上启动一个DNS查询。这能使浏览器获得请求对应的IP地址。
(2), 浏览器与远程Web服务器通过TCP三次握手协商来建立一个TCP/IP连接。该握手包括一个同步报文,一个同步-应答报文和一个应答报文,这三个报文在 浏览器和服务器之间传递。该握手首先由客户端尝试建立起通信,而后服务器应答并接受客户端的请求,最后由客户端发出该请求已经被接受的报文。
(3),一旦TCP/IP连接建立,浏览器会通过该连接向远程服务器发送HTTP的GET请求。远程服务器找到资源并使用HTTP响应返回该资源,值为200的HTTP响应状态表示一个正确的响应。
(4),此时,Web服务器提供资源服务,客户端开始下载资源。
请求返回后,便进入了我们关注的前端模块。简单来说,浏览器会解析HTML生成DOM Tree,其次会根据CSS生成CSS Rule Tree,而javascript又可以根据DOM API操作DOM。
3、 浏览器缓存机制
强制缓存优先于协商缓存进行,若强制缓存(Expires和Cache-Control)生效则直接使用缓存,若不生效则进行协商缓存(Last-Modified / If-Modified-Since和Etag / If-None-Match)。
协商缓存由服务器决定是否使用缓存,若协商缓存失效,那么代表该请求的缓存失效,重新获取请求结果,再存入浏览器缓存中;生效则返回304,继续使用缓存。
浏览器缓存有一些资源存在了memory cache(内存中)有一些资源存在了disk cache(磁盘中)
Memory Cache 也就是内存中的缓存,主要包含的是当前中页面中已经抓取到的资源,例如页面上已经下载的样式、脚本、图片等。读取内存中的数据肯定比磁盘快,内存缓存虽然读取高效,可是缓存持续性很短,会随着进程的释放而释放。一旦我们关闭 Tab 页面,内存中的缓存也就被释放了。
Disk Cache 也就是存储在硬盘中的缓存,读取速度慢点,但是什么都能存储到磁盘中,比之 Memory Cache 胜在容量和存储时效性上。
Push Cache(推送缓存)是 HTTP/2 中的内容,当以上三种缓存都没有命中时,它才会被使用。它只在会话(Session)中存在,一旦会话结束就被释放,并且缓存时间也很短暂,在Chrome浏览器中只有5分钟左右,同时它也并非严格执行HTTP头中的缓存指令。
浏览器每次发起请求,都会先在浏览器缓存中查找该请求的结果以及缓存标识。
浏览器每次拿到返回的请求结果都会将该结果和缓存标识存入浏览器缓存中。
4、 Service Worker
概述:一个服务器与浏览器之间的中间人角色,如果网站中注册了service worker那么它可以拦截当前网站所有的请求,进行判断(需要编写相应的判断程序),如果需要向服务器发起请求的就转给服务器,如果可以直接使用缓存的就直接返回缓存不再转给服务器。从而大大提高浏览体验。
缓存功能:
Service Worker 是运行在浏览器背后的独立线程,一般可以用来实现缓存功能。使用 Service Worker的话,传输协议必须为 HTTPS。Service Worker 的缓存与浏览器其他内建的缓存机制不同,它可以让我们自由控制缓存哪些文件、如何匹配缓存、如何读取缓存,并且缓存是持续性的。
离线应用:
service worker的出现并不是单纯的为解决精细化控制浏览器缓存问题的。它能充当代理服务器这一能力(通过拦截所有请求实现),能够实现HTTP缓存无法实现的功能:离线应用。因为在HTTP缓存策略下,如果一个资源过了服务器规定的到期时间,则必须要发起请求,一旦网络连接有问题,整个网站就会出现功能问题。而在service worker控制下的缓存,能够在代码中发现网络连接问题并直接返回缓存的资源。这种方式返回的响应对于浏览器来说是透明的,它会认为该响应就是服务器发送回来的资源。
6、 PWA的特点
渐进式网页应用,本质是webapp,借助一些新技术具备nativeapp的特性。
主屏图标,离线可用(service worker),消息通知,安全,体验度好。
无需审核、无需下载、持续更新。
缺点:调用原生应用,需借助第三方sdk。
7、 TypeScript的特点
为了帮助 JavaScript 的开发人员能像类似高级语言c#,Java那样编写代码,比如使用高级语言的强类型、面向对象、语法检查,代码编译等特点。
使用 TypeScript 可以帮你降低 JavaScript 弱语言的脆弱性,帮你减少由于不正确类型导致错误产生的风险,以及各种 JavaScript 版本混杂造成错误的风险。
主流前端框架(react、Angular、vue)已经集成TypeScript。TypeScript 紧跟 JavaScript 的发展,比如 ES7 、ES8、ES9 相关语言的新特性都支持,比浏览器支持的速度更快。这就意味着你能用最新的语言特性,编写质量更高的 JavaScript
引申:什么是强类型语言、弱类型语言
强类型语言,当你定义一个变量是某个类型,如果不经过代码显式转换(强制转化)过,它就永远都是这个类型,如果把它当做其他类型来用,就会报错
弱类型语言,你想把这个变量当做什么类型来用,就当做什么类型来用,语言的解析器会自动(隐式)转换。
8、 Nodejs
优点:
- 事件驱动,通过闭包很容易实现客户端的生命活期。
- 不用担心多线程,锁,并行计算的问题
- V8引擎速度非常快
- 对于游戏来说,写一遍游戏逻辑代码,前端后端通用
缺点:
- nodejs更新很快,可能会出现版本兼容
- nodejs还不算成熟,还没有大制作
- nodejs不像其他的服务器,对于不同的链接,不支持进程和线程操作
9、 nodejs框架及区别
Express主要基于Connect中间件框架,功能丰富,随取随用,并且框架自身封装了大量便利的功能,比如路由、视图处理等等。
而koa主要基于co中间件框架,框架自身并没集成太多功能,大部分功能需要用户自行require中间件去解决,但是由于其基于ES6 generator特性的中间件机制,解决了长期诟病的“callback hell”和麻烦的错误处理的问题,大受开发者欢迎。
Express 采用 callback 来处理异步,Koav1 采用 generator,Koav2采用 async/await。
10、 设计模式
a、单例模式: 应用该模式的一个类只有一个实例。即一个类只有一个对象实例。
b、工厂模式:是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式。工厂模式类似于现实生活中的工厂可以产生大量相似的商品,去做同样的事情,实现同样的效果,这时候需要使用工厂模式。
c、构造函数模式:使用构造函数的方法,既解决了重复实例化的问题,又解决了对象识别的问题。
d、观察者模式:定义了对象之间的一对多依赖,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。同步的方式
e、订阅/发布模式:异步的方式
f、适配器模式:将一个接口转换成客户端需要的接口而不需要去修改客户端代码,使得不兼容的代码可以一起工作
g、代理模式:为一个对象找一个替代对象,以便对原对象进行访问。代理模式是为了管控原有对象(本体)的访问,代理的初衷并不是为兼容,并主张代理与本体对外接口保持一致。
h、装饰器模式:作用是为对象添加功能,可添加多次,形成装饰链。而适配器只会对原有对象包装一次。
11、 MVC和MVVM
MVC:View视图(用户界面)、Controller控制器(业务逻辑)、Model模型(数据保存)
MVC通信模式,V-C-M-V
MVVM:View视图、ViewModel视图模型、Model模型。MVVM的通信模式,V-VM-M
View 与 Model 不发生联系,都通过 ViewModel传递。双向绑定。
ViewModel 有两个方向
A、将 Model 转化成 View ,即将后端传递的数据转化成所看到的页面。数据绑定。
B、将 View 转化成 Model ,即将所看到的页面转化成后端的数据。DOM 事件监听。
12、 vue双向数据绑定
VueJS 则使用 ES5 提供的 Object.defineProperty() 方法,监控对数据的操作,从而可以自动触发数据同步。Object.defineProperty() 定义的数据 set、get 函数中。
Vue的模式是m-v-vm模式,即(model-view-modelView),通过modelView作为中间层(即vm的实例),进行双向数据的绑定与变化。
- 通过建立虚拟dom树document.createDocumentFragment(),方法创建虚拟dom树。
- 一旦被监测的数据改变,会通过Object.defineProperty定义的数据拦截,截取到数据的变化。
- 截取到的数据变化,从而通过订阅——发布者模式,触发Watcher(观察者),从而改变虚拟dom的中的具体数据。
- 最后,通过更新虚拟dom的元素值,从而改变最后渲染dom树的值,完成双向绑定
引申:Object.defineProperty()
的作用就是直接在一个对象上定义一个新属性,或者修改一个已经存在的属性。
存取描述符:是由一对 getter、setter 函数功能来描述的属性
13、 Js 实现多线程
我们拥有一种叫做worker的东西。它是js里的一个类,而我们只需要创建它的实例就可以使用它。var worker = new Worker(js file path);
其中PostMessage(data)的参数是你要传递的数据,而onmessage是一个回调函数,只有在接受到数据时,onmessage会被回调,onmessage有一个隐藏的参数,那就是event,我们可以用event.data获取到传递过来的数据来更新主线程。
14、 Umijs
umi是一个可插拔的企业级react应用框架。umi以路由为基础的,支持类next.js的约定式路由,以及各种进阶的路由功能
umi配以完善的插件体系,覆盖从源码到构建产物的每个生命周期
umi是蚂蚁金服的底层前端框架
umi 可以简单地理解为 roadhog + 路由,思路类似 next.js/nuxt.js,辅以一套插件机制,目的是通过框架的方式简化 React 开发
特性
1.开箱即用:内置react、react-router等
2.类next.js且功能完备的路由约定,同时支持配置的路由方式
3.完善的插件体系,覆盖从源码到构建产物的每个生命周期
4.高性能,通过插件支持PWA(渐进式WEB应用)、以路由为单位的code splitting等
5.支持静态页面导出,适配各种环境
6.开发启动快,支持一点开启dll和hard-source-webpack-plugin等
7.一键兼容到IE9,基于umi-plugin-polyfills
8.完善的TypeScript支持,包括d.ts定义和umi test
9,与dva的数据流的深入融合,支持duck directory、model的自动加载、code splitting等等
15、真实dom与虚拟dom的区别
真实DOM
DOM表示为树数据结构。因此,DOM的更改和更新很快。但是在更改之后,必须重新渲染已更新的元素及其子元素以更新应用程序UI。UI的重新渲染或重新绘制使它变慢。因此,您拥有的UI组件越多,DOM更新的成本就越高,因为每次DOM更新都需要重新渲染它们。
虚拟DOM
虚拟DOM是一个js对象。虚拟DOM性能要比真实DOM好得多。虚拟DOM只是DOM的虚拟表示。每当我们的应用程序状态更改时,虚拟DOM就会更新,而不是真实DOM。
虚拟DOM如何更快?
传统的 Web 应用中每次数据的微小变动都会引起 DOM 树的重新渲染。
虚拟DOM的目的是将所有操作累加起来,统计计算出所有的变化后,统一更新一次DOM。
16、webpack打包原理
webpack打包原理是根据文件间的依赖关系对其进行静态分析,将这些模块按指定规则生成静态资源,当 webpack处理程序时,它会递归地构建一个依赖关系图,其中包含应用程序需要的每个模块,将所有这些模块打包成一个或多个bundle。
webpack有两种组织模块的依赖方式,同步、异步。异步依赖将作为分割点,形成一个新的块;在优化了依赖树之后,每一个异步区块都将作为一个文件被打包。
webpack有一个智能解析器,几乎可以处理任何第三方库。无论它们的模块形式是CommonJS、AMD还是普通的JS文件;甚至在加载依赖的时候,允许使用动态表require("、/templates/"+name+"、jade")
202207补充:
1、vue双向数据绑定原理
通过Object.definePropert()监听数据变化,通过get、set方法实现双向数据绑定。
vue3.0数据监听方式变成了Proxy。消除了Object.defineProperty现有的限制(例如无法检测新的属性添加),并提供更好的性能。
2、vue3.0优势
(1)性能比2.0快:diff算法的优化。vue2.0虚拟dom是全量比较的。在vue3中,增加了静态标记PatchFlag
(2)体积比Vue2.x更小:按需编译。(Tree shaking)
(3)compostion api组合API:将逻辑相关的代码放在一起,近而有利于代码的维护。
(4)TypeScript 以及 PWA 的支持
3、vue和react的异同
共同点:
(1)都使用虚拟dom。
(2)提供了响应式和组件化的视图组件。
(3)关注核心代码,将其他功能如路由和全局状态管理交给相关的库。(vue-router、vuex、react-router、redux等等)
区别:
(1)核心思想不同:
Vue定位是降低前端开发的门槛,更快地上手开发。特点:灵活易用的渐进式框架,进行数据拦截/代理,它对侦测数据的变化更敏感、更精确。
React定位是提出 UI 开发的新思路。推崇函数式编程(纯组件),数据不可变以及单向数据流,需要双向的地方可借助onChange和setState来实现。
(2)组件写法差异:
React推荐的做法是JSX + inline style, 把 HTML 和 CSS 全都写进 JavaScript 中,即 all in js;
Vue 推荐的做法是 template 的单文件组件格式,即 html,css,JS 写在同一个文件(vue也支持JSX写法)
(3)响应式原理不同
Vue:递归监听data的所有属性,直接修改。当数据改变时,自动找到引用组件重新渲染。
React:基于状态机,手动优化,数据不可变,需要setState驱动新的state替换老的state。当数据改变时,以组件为根目录,默认全部重新渲染。
(4)应用场景
Vue
1、构建数据简单中小型应用时:vue提供简单明了的书写模板、大量api、指令等等,可快速上手、开发项目
2、应用尽可能的小和快:随着vue3.0的发布,vue的体积进一步缩小,远小于react的体积,也配合diff算法,采用proxy去实现双向绑定,渲染大幅度提升
React
1、构建一个大型应用项目时:React的渲染系统可配置性更强
2、适用于Web端和原生APP:React Native是一个使用Javascript构建移动端原生应用程序(iOS,Android)的库。
4、箭头函数的注意事项
(1)箭头函数没有自己的this
对象。函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
(2)不可以当作构造函数,即不可以使用new命令,否则会抛出一个错误。
(3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
(4)不可以使用yield命令,因此箭头函数不能用作 Generator 函数。
5、异步编程实现
(1)回调函数
(2)事件监听
(3)发布/订阅(观察者模式)
(4)Promise 对象
(5)Generator 函数
(6)async 函数
6、js单线程和任务队列
JavaScript是单线程,这已经成了这门语言的核心特征。
为了利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。
异步执行的运行机制如下:
(1)所有同步任务都在主线程上执行,形成一个执行栈
(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
(4)主线程不断重复执行上面的第三步。
7、Diff算法
由于在浏览器中操作DOM是很昂贵的,频繁的操作DOM,会产生一定的性能问题,这就是虚拟DOM的产生原因。
虚拟DOM本质上是JavaScript对象,是对真实DOM的抽象状态变更时,记录新树与旧树的差异,最后把差异更新到真正的DOM中。
diff算法的作用:用来修改DOM的一小段,不会引起dom树的重绘
更高效的Diff算法:
React的开发者结合Web界面的特点做出了两个大胆的假设,使得Diff算法复杂度直接从O(n^3)降低到O(n),假设如下:
(1)两个相同组件产生类似的DOM结构,不同的组件产生不同的DOM结构;
(2)对于同一层次的一组子节点,它们可以通过唯一的id进行区分。
新的Diff算法是逐层进行比较,只比较同一层次的节点,不会跨层次比较,大大降低了复杂度。
不同类型节点的比较:Diff算法会直接删除旧的节点及其子节点并插入新的节点
相同类型节点的比较:若是两个节点类型相同时,Diff算法会重新设置该节点的属性,从而实现节点的更新。
8、跨站脚本攻击(XSS)和跨站请求伪造(CSRF)
XSS攻击又称为跨站脚本,XSS的重点在于脚本的执行。XSS是一种经常出现在Web应用程序中的计算机安全漏洞,是由于Web应用程序对用户的输入过滤不足而产生的,它允许恶意web用户将代码植入到提供给其它用户使用的页面中。
常见的XSS攻击有三种:反射型XSS攻击、DOM-based型XSS攻击、存储型XSS攻击
预防措施:
1、对输入、输出结果进行过滤和必要的转义
2、尽量使用post,使用get方式时对路径长度进行限制
3、使用httponly禁止黑客通过脚本获取用户cookie数据,但这样无法完全阻止xss攻击,因为发送http请求并不需要主动获取cookie
CSRF全称cross-site request forgery,名为跨站请求伪造,顾名思义就是黑客伪装成用户身份来执行一些非用户自愿的恶意以及非法操作
常见攻击情景:
用户A经常访问博客网站B,用户C发现网站B存在CSRF漏洞,想尽了各种办法勾引用户A访问了C写好的危险网站D,而此时用户A的cookie信息还没有失效,危险网站D中有向网站B求请求的非法操作,这样用户在不知情的情况下就被操控了。
这个时候就会有一个疑问,浏览器本身有同源策略啊,为什么在网站D还可以请求网站B的api,要记住浏览器对img、iframe和script的src是没有同源限制的!所以黑客完全可以利用动态添加这些标签的方法来实现跨站请求。
预防措施:
1、验证码
2、tokenId令牌
3、服务端判断请求的Referer是否正确
CSRF和XSS的区别:
1、CSRF需要登陆后操作,XSS不需要
2、CSRF是请求页面api来实现非法操作,XSS是向当前页面植入js脚本来修改页面内容。
9、JSBridge原理
1、类比Client/Server 2、将Native端原生接口封装成Javascript接口 3、将Web端原生接口封装成Native端原生接口 4、Web端和Native端之间双向通信
JSBridge实现方式:
1)原生端调用web端只有执行js代码一种方式
2)web调用原生端,有两种实现方式:
a、拦截WebView请求的URL Schema
1、URL Schema : 是URL的一种请求格式 【<prototal>://<domain>/<path>?<query>】
2、自定义JSBridge通信的URL Schema 【jsbridge://<method>?<params> ------ 如:jsbridge://showToast?text=hello 】
优点:兼容性好
缺点: 不直观、url长度有限制
b、向WebView注入JS API
App 向webView注入一个js对象提供给webView用, 方法名、参数和app方法一致