HTML
DTD(文档类型定义)
- DOCTYPE:严格( strict )和过渡( transitional )
- 包含严格 DTD 的 DOCTYPE 常常导致页面以标准模式呈现。
- 包含过度 DTD 和 URI 的 DOCTYPE 也导致页面以标准模式呈现。
- 但是有过度 DTD 而没有 URI 会导致页面以混杂模式呈现。
- DOCTYPE 不存在或形式不正确会导致 HTML 和 XHTML 文档以混杂模式呈现。
内核??
1)Trident: IE 以Trident 作为内核引擎;
2) Gecko: Firefox 是基于 Gecko 开发;
3)WebKit: Safari, Google Chrome,傲游3,猎豹浏览器,百度浏览器 opera浏览器;
mozilla内核 (firefox,flock等) -moz
webkit内核(safari,chrome等) -webkit
opera内核(opera浏览器) -o
trident内核(ie浏览器) -ms
CSS
选择器
- id 选择器,class 选择器,标签选择器,伪元素(before/after/first-letter/::selection)选择器,伪类(hover/first-child/checked)选择器
- !important > id 选择器 > class 选择器 > 标签选择器 / 属性选择器=伪类选择器
- 内联样式> 内部样式 > 外部样式 > 浏览器用户自定义样式 > 浏览器默认样式
不能冒泡事件
resize
scroll
focus
blur
mouseenter
mouseleave
load
unload
media相关事件
flex
- flex-flow
- flex-direction
- flex-wrap
- justify-content
1 | .flex{ |
- align-items: 项目在交叉轴上的对齐方式
- align-content: 多个项目多根轴线的对齐方式
- order
- flex-grow
- flex-shrink: 哪个项目缩小 值设为0 ;
- align-self
overflow
auto
scroll
visible
hidden
text-overflow
属性: 值为clip
是修剪文本;ellipsis
为显示省略符号来表被修剪的文本;string
为使用给定的字符串来代表被修剪的文本。
Position
fixed
absolute
static
relative
inherit
sticky
sticky
:relative和固定定位fixed的结合
BFC(块级格式化上下文,用于清楚浮动,防止margin重叠等)
- 块格式化上下文,这是一个独立的渲染区域,规定了内部如何布局,并且这个区域的子元素不会影响到外面的元素,布局规则是内部box垂直放置。
- 那些元素会生成BFC:
- 根元素
- float不为none的元素
- position为fixed和absolute的元素
- display为inline-block、table-cell、table-caption,flex,inline-flex的元素
- overflow不为visible的元素
垂直居中的方法
margin:auto
法: 脱离文档流
1 | img{ |
margin:-100px
负值法table-cell
: 未脱离文档流
1 | div{ |
- 父元素设置
display:flex
,并且设置align-items:center;
justify-content:center
; transform
方法1
2
3
4
5div{
top: 50%;
left:50%;
transform: translate(-50%, -50%);
}
浮动清除
- 使用
clear:both
的 空元素 /:after
伪元素 / 后面的内容 overflow:hidden;
或overflow:auto
- 浮动的元素的容器添加浮动。但影响布局,不推荐使用。
三行
- 圣杯布局
float
+负margin+padding:- center先渲染;
margin-left: -100%; margin-right: -200px
- container设置padding
left: -200px; right: -200px
- 双翼布局
float
+设置main(margin+overflow) - flex: container的
display:flex
+flex-shrink: 0
不收缩 - 绝对定位: center的
left: 200px; right: 200px
- 缺点:两栏高度不够,则center也被压缩
- grid: container的
display:grid
+grid-template-columns: 200px auto 200px;
- table-cell布局:
- div的
display: table-cell
- left和right设置
width
和min-width
- div的
img可替换元素拥有内置宽高
- img是
inline
行内元素,但也是可替换元素。 - 可替换元素:img input option canvas 等。
- textarea button是浏览器默认的内联块元素
JS
Flash
- Flash提供了ExternalInterface接口与JavaScript通信:两个方法:call和addCallback
- 作用:call让Flash调用js里的方法,addCallback是用来注册flash函数让js调用。
this的指向
- 默认绑定:全局环境中,this默认绑定到window。
- 隐式绑定:被某个对象包含的函数调用时,this隐式绑定到该直接对象。
- 隐式丢失:隐式丢失是指被隐式绑定的函数丢失绑定对象,从而默认绑定到window。
- 显式绑定:通过call()、apply()、bind()方法把对象绑定到this上,叫做显式绑定。
- new绑定:构造函数调用,就是new时。对于this绑定来说,称为new绑定。
原型 proto
- 所有的引用类型(数组、对象、函数)/ 实例对象,都有一个
__proto__
(隐式原型)私有属性, 指向(完全相等)它的构造函数的原型对象prototype
属性值 - 所有的函数,都有一个
prototype
(显式原型)属性, 指向一个对象typeof f.prototype // "object"
- 对于构造函数生成实例时,该实例的原型
__proto__
就指向构造函数的prototype
:dog.__proto__ == Animal.prototype
- 原型对象也有一个自己的原型对象
- 对于构造函数生成实例时,该实例的原型
[[prototype]]
是对象的私有属性,而prototype
却是只有函数才有的属性- constructor是对象才有的属性,指向该对象的构造函数
参考
call()
和apply()
和bind()
- 在使用
call(this, ...arr)
方法时,传递给函数的参数必须逐个列举出来。 - 使用
apply(this, arr)
时,传递给函数的是参数数组 bind(this, ...arr)
返回的是函数, 不会立即执行
1 | add.call(o, 5, 7); |
new操作符做了哪些事?
- new 操作符新建了一个空对象,这个对象原型指向构造函数的prototype,执行构造函数后返回这个对象。
闭包
优点:
- 闭包就是能够读取其他函数内部变量的函数,把函数内部和外部连接起来的工具
- 子函数在外调用,子函数所在的父函数的作用域不会被释放:延长局部变量的生命周期,局部变量不可以被内存释放,因为要让外部可以访问到这个变量
缺点: - 由于闭包让函数中的变量都被保存在内存中,内存消耗很大,会造成网页的性能问题。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
- 闭包会在父函数外部,改变父函数内部变量的值。所以,如果把父函数当作对象(object)使用,把闭包当作它的公用方法,把内部变量当作它的私有属性,这时一定要小心,不要随便改变父函数内部变量的值。
特点
1、函数套函数,闭包一定有嵌套函数
2、外层函数一定有局部变量,且内层函数一定操作了外层函数的这个变量
3、外层函数一定把内层函数返回外部,使用return
(两道题理解闭包和箭头函数this)[https://www.cnblogs.com/echolun/p/11969938.html]
异步回调地狱
promise
、generator
、async/await
懒加载
- 主要目的是作为服务器前端的优化,减少请求数或延迟请求数。
- 预加载:提前加载图片,当用户需要查看时可直接从本地缓存中渲染。其差别是懒加载对服务器前端有一定的缓解压力作用,预加载则会增加服务器前端压力。
Commonjs、AMD和CMD
- Commonjs:开始于服务器端的模块化,每个模块都是一个单独的作用域。模块输出,
modules.exports
,模块加载require()
引入模块。 - AMD:中文名异步模块定义的意思。加载依赖函数的时候是异步加载的,这样浏览器不会失去响应。它指定的回调函数,只有前面的模块加载成功,才会去执行。
- requireJS: 实现了AMD规范,主要用于解决下述两个问题。
- 多个文件有依赖关系,被依赖的文件需要早于依赖它的文件加载到浏览器
- 加载的时候浏览器会停止页面渲染,加载文件越多,页面失去响应的时间越长。
- requireJS: 实现了AMD规范,主要用于解决下述两个问题。
- CMD:SeaJS
==
,===
和Object.is
===
严格等于,不强制转换成NumberObject.is
主要的区别就是+0 != -0
而NaN==NaN
js控制一次加载一张图片,加载完后再加载下一张
obj.onload
事件,该事件可以判断该对象是否加载完成readyState="complate"
时,就可以表示图片加载完成
判断类型方法
typeof(表达式)
/typeof name
: 返回的都是字符串类型"undefined"
"boolean"
"string"
"number"
"function"
: class本质也是function
"object"
: 对象类型的变量或值,或者null(这个是js历史遗留问题,将null作为object类型处理)- 不能判断数组,
typeof [] === "object"
- 判断一些创建的对象,它们都会返回
"object"
,有时我们需要判断该实例是否为某个对象的实例,那么这个时候需要用到instanceof
运算符
- 不能判断数组,
instanceof
: 判断已知对象类型(大写开头),返回true/false
- 某个实例对象是否属于它的父类型(基于原型链)
1
2
3
4
5
6
7
8
9
10
11c instanceof C; // true
c instanceof Object; // true
C.prototype instanceof Object; // true
"" instanceof String // false
({}) instanceof Object; // true, 尽管原型没有定义
Number instanceof Number //false
String instanceof String //false
Object instanceof Object //true
Function instanceof Function //trueObject.prototype.toString.call()
1 | Object.prototype.toString.call([]); // === "[object Array]" |
constructor
: 其属性定义P.prototype.constructor
constructor
在类继承时会出错1
2
3c.constructor === C;
c.constructor === C.prototype.constructor;
[].constructor === Array;
数组去重:两层循环/自身键不可重复性
- Set去重(ES6):
Array.from(new Set(array))
- 无法去掉
{}
空对象
- 无法去掉
- Map去重:
map.has
和map.set
splice
: for 嵌套 for,找到相同就删去: NaN和{}没有去重,两个null直接消失了indexOf
/includes
: 新建一个空的结果数组,如没有result.indexOf(arr[i] === -1)
/!array.includes(arr[i])
,就result.push(arr[i])
进去- indexOf 不能判断
NaN
以及 不能去掉{}
空对象 - includes不能去掉
{}
空对象
- indexOf 不能判断
hasOwnProperty
:Object
键值对去重:Object[value1] = true
: 可以去{}
空对象sort()
: 排序后,遍历并对相邻元素比对,不与之前的相等就push进新数组filter
:return arr.indexOf(item, 0) === index
判断条件:第一个索引是当前索引值即返回hasOwnProperty
: 存为集合{<type>item: true/false}
:return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true)
: 可以去{}
空对象
- 排序后,递归去重
空对象
Object.getOwnPropertyNames()
或者Object.keys()
返回数组的length为0- 如
Object.prototype.isPrototypeOf(obj) && Object.keys(obj).length === 0
- 如
for...in
+hasOwnProperty()
- 注意
for...in
会将对象原型链上的属性也枚举出来,所以要借hasOwnProperty()
方法来判断是不是对象本身的属性
- 注意
JSON.stringify()
性能优化
- 减少请求数量、
- 文件合并
- 图片处理:雪碧图、Base64格式内嵌在HTML中
- 减少重定向,∵会延迟整个HTML文档的传输:http重定向到https,要使用301永久重定向,而不是302临时重定向
- 使用缓存
- 不使用CSS @import:会造成额外的请求
- 避免使用空的src和href:会重定向到当前的页面地址
- 减小资源大小、
- 资源压缩
- 开启gzip, CDN托管,data缓存 ,图片服务器
- 优化网络连接、
- 使用CDN分发:解决网络拥挤的状况,提高用户访问网站的响应速度
- 使用DNS预解析:提前解析之后可能会用到的域名,使解析结果缓存到系统缓存中
- 持久连接:使用keep-alive或presistent来建立持久连接,持久连接降低了时延和连接建立的开销
- 优化资源加载、
- 资源加载位置:
- CSS文件放在head中,先外链,后本页
- JS文件放在body底部,先外链,后本页
- 处理页面、处理页面布局的JS文件放在head中,如babel-polyfill.js文件、flexible.js文件
- body中间尽量不写style标签和script标签
- 页面中空的 href 和 src 会阻塞页面其他资源的加载 (阻塞下载进程)
- 资源懒加载与资源预加载
- 资源加载位置:
- 减少重绘回流
- 使用CSS3代码代替JS动画
- 用innerHTML代替DOM操作,减少DOM操作次数,优化javascript性能。
- 当需要设置的样式很多时设置
className
而不是直接操作style
。
- 使用性能更好的API
- 构建优化: 尽量向前端优化、减少数据库操作、减少磁盘IO
- 向前端优化指的是,在不影响功能和体验的情况下,能在浏览器执行的不要在服务端执行,
- 能在缓存服务器上直接返回的不要到应用服务器,程序能直接取得的结果不要到外部取得,
- 本机内能取得的数据不要到远程取,内存能取到的不要到磁盘取,缓存中有的不要去数据库查询。
- 减少数据库操作指减少更新次数、缓存结果减少查询次数、将数据库执行的操作尽可能的让你的程序完成(例如join查询),
- 减少磁盘IO指尽量不使用文件系统作为缓存、减少读写文件次数等。程序优化永远要优化慢的部分,换语言是无法“优化”的。
基本数据类型 / 引用数据类型
- 基本数据类型:
undefined
、null
、number
、boolean
、string
、symbol
- 引用数据类型:
Object
,Array
,Function
,Date
,Math
, 正则 等
评价框架(ant-design)
优点:组件非常全面,样式效果也都比较不错。
缺点:框架自定义程度低,默认UI风格修改困难。
重排和重绘的区别
浏览器渲染
- 解析html生成DOM树,解析css,生成CSSOM树,将DOM树和CSSOM树结合,生成渲染树;
- 根据渲染树,浏览器可以计算出网页中有哪些节点,各节点的CSS以及从属关系 - 重排
- 根据渲染树以及回流得到的节点信息,计算出每个节点在屏幕中的位置 - 重绘
- 最后将得到的节点位置信息交给浏览器的图形处理程序,让浏览器中显示页面
重排 Reflow
- 当渲染树中的节点信息发生了大小、边距等问题,重新计算各节点和css具体的大小和位置的过程。
- e.g. 使用了
width: 50%
,此时需要将50%转换为具体的像素,这个计算的过程 - 造成回流的操作:
- 布局流相关操作:box模型的相关操作 / 定位 / 浮动
- 改变节点内容
- css: width height padding border margin
重绘 repaint
- 当节点的部分属性发生变化,但不影响布局,只需要重新计算节点在屏幕中的绝对位置并渲染的过程,就叫重绘。
- e.g. 改变元素的背景颜色、字体颜色等操作
- 回流一定会重绘,但重绘不一定会引起回流。
减少回流和重绘
- 操作多个css属性:改为
div.style.cssText
一次修改多个 / 定义一个类名 - 脱离标准流的操作:先隐藏元素 / 拷贝节点/ 使用文档碎片
- 避免多次触发布局:先获取滚动过的距离,之后只做数字递增
冒泡 和 捕获
- 冒泡中
false
:内部元素先被触发,然后再触发外部元素 - 捕获中
true
:外部元素先被触发,在触发内部元素
防抖 和 节流
- 防抖:将多次调用合并称一次,也就是在一定时间内,限制事件被触发的次数
- 节流:在一定时间内至少执行一次事件,而不是一触发事件就调用一次,这样就会减少资源浪费。
箭头函数
- 箭头函数没有this,通过作用域链来确定this的值,比如this绑定的是最近一层非箭头函数的this
- 箭头函数没有自己的
arguments
对象,但是可以访问外围函数的arguments对象 - 不能通过
new
关键字调用,同样也没有new.target
值和原型
进程和线程 区别
- 进程是资源分配最小单位,线程是程序执行的最小单位;
- 进程有自己独立的地址空间,每启动一个进程,系统都会分配地址空间;线程没有独立的地址空间,它使用相同的地址空间共享数据
- 多进程程序更安全,因为一个进程死掉不会对另一个进程造成影响(因为有独立的地址空间);多线程程序更不易维护,一个线程死掉,整个进程就死掉了(因为共享地址空间);
- 进程对资源保护要求高,开销大,效率相对较低,线程资源保护要求不高,但开销小,效率高,可频繁切换;
JSDOM 事件流
- 三个阶段:
- 事件捕获阶段
- 处于目标阶段
- 事件冒泡阶段
ES6
- ES6在变量的声明和定义方面增加了let、const声明变量,有局部变量的概念,赋值中有比较吸引人的解构赋值,
- ES6也 引入了新的数据类型
symbol
,新的数据结构set
和map
. symbol可以通过typeof检测出来, - 箭头函数
- 为解决异步回调问题,引入了
promise
和generator
, - 还有最为吸引人了实现
Class
,通过Class可以更好的面向对象编程, - 模块: 使用模块加载方便模块化编程.
重要的特性:
- 块级作用域:ES5只有全局作用域和函数作用域,块级作用域的好处是不再需要立即执行的函数表达式,循环体中的闭包不再有问题
- rest参数:用于获取函数的多余参数,这样就不需要使用arguments对象了,
- promise:一种异步编程的解决方案,比传统的解决方案回调函数和事件更合理强大
- 模块化:其模块功能主要有两个命令构成,
export
和import
,export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能
垃圾回收
- 标记清除:
- 计数引用:
参考
Bootstrap
- 轻量级的开发响应式页面的框架
- 全局CSS,组件,JS插件
- 栅格系统:将页面分为12个等分(CSS3@media媒体查询)
- xs 手机
- sm 平板
- md PC
- lg 超大屏幕
React
Redux
- 更好的处理应用的共享状态
- 组件化的应用有很多层级关系,而redux就是把共享状态都存在store里,就不需要把状态当做属性向下一个一个地传递。
数据流向
组件想要获取State,用ActionCreator创建了一个请求交给Store, Store借助Reducer确认State的状态,再返回给Store一个结果,Store再把这个State转给组件。
Provider
connect
connect(mapStateToProps?, mapDispatchToProps?, mergeProps?, options?)(component)
React单项数据流
数据是从父组件到子组件的流动方向。把组件看成是一个函数,那么他接受props
作为参数,内部由state
作为函数的内部参数,返回一个虚拟dom的实现。
props
: 顶层组件初始化props
,那么React会向下遍历整颗组件树,重新渲染相关的子组件state
: 表示的是每个组件中内部的的状态,这些状态只在组件内部改变。
react生命周期函数 / react组件的生命周期
constructor()
构造方法- 初始化state
componentWillMount()
组件挂载之前- 可以
setState
,render()
后可以看到更新后的state,不会触发重复渲染
- 可以
render()
用来渲染dom- 不在render方法里面修改state
componentDidMount()
组件挂载完成后- 发起异步请求,并在异步请求中可以进行
setState
- 只有到这里才能获取到真实的dom.
- 发起异步请求,并在异步请求中可以进行
componentWillReceiveProps(nextProps)
props即将变化之前- 可以通过参数
nextProps
获取变化后的props参数,通过this.props
访问之前的props
- 可以通过参数
shouldComponentUpdate(nextProps, nextState)
是否重新渲染- 每次调用setState后都会重新渲染,如果不影响界面展示,可以在这里做判断false,优化渲染效率
componentWillUpdate(nextProps, nextState)
- 不能
setState
- 不能
componentDidUpdate()
完成组件渲染- 除了首次render之后调用
componentDidMount
,其它render结束之后都是调用componentDidUpdate
。
- 除了首次render之后调用
componentWillUnmount()
组件即将被卸载
React 对比 vue
- 就是简单而且与原生JavaScript非常接近
- 看到很多地方在说react其实是一个UI库,并不是一个完整的框架。他只是告诉我们如何创建组件以及组件之间如何进行数据传递。
- 没有真正意义上的双向绑定。不能直接更新状态数据,必须通过
setState()
更新指定数据 - 状态管理
setState()
手动的;vue data属性进行自动管理 - React所有的模板使用的是JavaScript的语法扩展;Vue所有的模板使用的是近似常规HTML,只不过是新添加了一些属性
setState之后的流程
- React 会将传入的参数对象与组件当前的状态合并
- 并构建 React 元素树b
- 算出新的树与老树的节点差异(diff算法),然后根据差异对界面进行最小化重渲染
diff算法
React 通过大胆的假设,制定对应的 diff 策略,将 O(n3) 复杂度的问题转换成 O(n) 复杂度的问题
tree diff:对VDOM树分层比较,只对同一层次节点进行比较。
- 如果有节点不存在的话,就把该节点和他的子节点完全删除,不会再进一步比较。也就是直接删除不复用已有节点,只需要遍历一次,就能完成整棵DOM树的比较。
- 如果有节点跨层级操作: 就新建再删除 不会复用。
component diff:对组件间的比较
- 同类型组件:先看
shouldComponentUpdate
,需要更新就按层级比较VDOM树即可;如果组件改变了但VDOM树没变的,我们可以设置返回false,可以节省时间。 - 不同类型的组件:因为不同类生成不同树结构,所以不会复用,也是直接替换整个组件下的所有子节点,即使他们是结构相似的
- 同类型组件:先看
通过设置唯一 key 策略,对 element 也就是对同一层级的子节点比较
- 有key:判断老集合中是否存在相同的节点,如果没有则创建,有就判断是否需要移动,可以复用。
- 没key:不一样就之间删除重建,不能复用子节点
参考
Node
Express
Express是一个简洁的node.js Web应用框架,帮助创建各种 Web 应用,和丰富的 HTTP 工具
req取参方法
req.body
需要
body-parser
中间件,解析POST请求中的数据:例如 form data中的name
passport
等可以用req.body.name
获取req.params
url中的参数解析:例如 在
route/user/:name
,req.params.name
可以访问到name属性和在路由中命名的参数名是一一对应的
1 | // GET route/user/tju |
req.query
- 解析GET里的参数,两个或以上参数用 & 连接
1 | // GET /search?q=wayne |
req.cookies
- 使用
cookie-parser
中间件的时候,这个属性是一个对象,其包含了请求发送过来的 cookies
req.route
- 当前匹配的路由,其为一串字符
res属性 方法
res.send([body]) / res.json()
- 发送HTTP响应
- body参数可以是一个Buffer对象,一个字符串,一个对象,或者一个数组
res.redirect([status,]path)
计算机网络
cdn原理 (Content Delivery Network 内容分发网络)
- 采用各种缓存服务器,利用在用户访问相对集中的地区或网络,直接响应
Cookie、sessionStorage、localStorage
- Cookie 和 Session
- cookie数据存放在客户的浏览器上,session数据放在服务器上。
- cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗。【考虑到安全】应当使用session。
- session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能。【考虑到减轻服务器性能】,应当使用COOKIE。
- 单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
- sessionStorage 和 localStorage
- local始终有效,local得手动清除;session没关闭窗口前有效
- 所有同源窗口共享
indexed DB 和 Web SQL
JS实现跨域
- JSONP:通过动态创建script,再请求一个带参网址实现跨域通信
- 返回一个函数调用,其参数就是data
- 只能用get方法
- CORS: 服务端设置
Access-Control-Allow-Origin
- 简单请求 / 预检请求
- 服务器代理
- document.domain + iframe跨域(主域相同,子域不同的跨域应用场景)
- 赋成当前的域名或者一级域名
news.baidu.com
和map.baidu.com
都改成baidu.com/www.baidu.com
可以,但改成qq.com
就会报错 - 两个页面都通过js强制设置document.domain为基础主域,就实现了同域
- 赋成当前的域名或者一级域名
- location.hash + iframe(主域不同, 通过中间页来实现)
- 三个页面,不同域之间利用iframe的
location.hash
传值,相同域之间直接js访问来通信。 - ∵改变hash并不会导致页面刷新,所以可以利用hash值来进行数据传递
- a的iframe的src指向b域名下的页面,后面的hash值可以做参数传递用→b响应请求后再修改a的iframe的hash值来传递数据→a上加一个定时器,隔一段时间来判断location.hash的值有没有变化,一有变化就获取hash值
- 三个页面,不同域之间利用iframe的
- window.name + iframe跨域 (主域不同)
- 只要不关闭页面,仅仅改变网址的话,
window.name
是不会变的,而且每一个打开的页面都能获取并修改window.name
的值。 - b通过
window.name
提供数据 → 在a中的iframe指向b → 绑定事件中就可以通过iframe.contentWindow.name
获取,但不能直接访问因为还不同源,还需要将iframe地址改成与a同源的一个地址:∵地址改变不会改变window.name
的值,所以iframe.contentWindow.name
的值还是之前的值
- 只要不关闭页面,仅仅改变网址的话,
- postMessage跨域
参考
HTTP访问控制(CORS)
跨域资源共享:使用额外的 HTTP 头来告诉浏览器 让运行在一个 origin (domain) 上的Web应用被准许访问来自不同源服务器上的指定的资源。当一个资源从与该资源本身所在的服务器不同的域、协议或端口请求一个资源时,资源会发起一个跨域 HTTP 请求。
- 简单请求:不会触发 CORS 预检请求
- 使用
GET
HEAD
POST
- 除了被用户代理自动设置的首部字段(例如 Connection ,User-Agent)和在 Fetch 规范中定义为 禁用首部名称 的其他首部,允许人为设置的字段为 Fetch 规范定义的 对 CORS 安全的首部字段集合。该集合为:
Accept
Accept-Language
Content-Language
Content-Type (需要注意额外的限制)
DPR
Downlink
Save-Data
Viewport-Width
Width
Content-Type 的值仅限于下列三者之一:
text/plain
multipart/form-data
application/x-www-form-urlencoded
请求中的任意XMLHttpRequestUpload 对象均没有注册任何事件监听器;XMLHttpRequestUpload 对象可以使用 XMLHttpRequest.upload 属性访问。
请求中没有使用 ReadableStream 对象。
- 预检请求
与前述简单请求不同,“需预检的请求”要求必须首先使用 OPTIONS 方法发起一个预检请求到服务
从输入url到显示页面这个过程发生了什么
- url通过DNS解析找对应的服务器ip
- 先看浏览器缓存→系统本地缓存,如果本地缓存服务器中找不到结果,发送过程中也会查看路由器缓存,如果都没有就会向根服务器查询
- 根服务器
“”
里面记录的都是各个顶级域cn com
的服务器的位置, 一步一步拿到查询的url位置,并向它请求地址。(之后会在本地进行缓存)
- 浏览器向服务器发起TCP连接,建立三次握手,握手成功后,浏览器向服务器发送http请求,请求数据包。
- 服务器处理请求并返回HTTP报文
- 浏览器解析,构建DOM树包括CssOM树,合并为渲染树,渲染页面
- 浏览器下载HTML后,首先解析头部代码,进行样式表下载,然后继续向下解析HTML代码,构建DOM树,同时进行样式下载。当DOM树构建完成后,立即开始构造CSSOM树。当两棵树构建完毕,构建渲染树,然后进行绘制。
- js 会阻塞 DOM 生成,而样式文件又会阻塞 js 的执行
- 连接结束
DNS域名系统
域名和IP地址相互映射的一个分布式数据库,通过域名解析得到主机对应的IP地址
页面渲染机制
- DomContentLoad — paint — Load
- HTML的加载 → 其他静态资源加载:
- html顺序加载,其中js会阻塞后续dom和资源加载;而如果代码里引用了外部的 CSS 文件,那么在执行 js 之前,还需要等待外部的 CSS 文件下载完成,并解析生成 CSSOM 对象之后,才能执行 js 脚本。
- 浏览器会使用prefetch对引用的资源提前下载
- 没有defer或async,HTML的解析会停下来,浏览器会立即加载并执行指定的脚本,等JS下载完执行结束后才继续解析HTML,防止JS修改已经完成的解析结果。∴没有操作 DOM 可以设置为异步加载
- 有async,下载异步,执行同步,加载完就执行
- 有defer,加载异步,但是script.js的执行要在所有元素解析完成之后,DOMContentLoaded事件触发之前完成
html解析流程
- js会阻塞dom的解析,但js不会阻塞dom的渲染
- css
- 单个css: 是不阻塞dom解析的,但是css是阻塞dom渲染的
- 后面还有js:css是阻塞了dom的解析的,js可能会改变css属性,所有必须等到它前面的css执行完毕。
- img
- 没有css:img对dom的解析没有阻塞,但是会阻塞dom的渲染
- css的解析是在图片首次解码前的
TCP/IP的网络模型
是一系列网络协议的总合,可以让计算机之间进行信息交换
四层架构从下到上:链路层,网络层,传输层,应用层
- 物理数据链路层:是负责建立电路连接,是物理基础,典型的协议包括以太网,ADSL等,
- 网络层:负责分配地址和传送二进制数据,主要协议是IP协议
- 传输层:负责传送文本数据,主要协议是TCP和UDP
- 应用层:负责文件传输的,包括各种最终形态的数据,是直接与用户信息交互的层,主要协议是http(ftp
OSI七层模型
从上到下分别是:
- 应用层:文件传输,常用协议HTTP https(FTP DNS
- 表示层:数据格式化,代码转换,数据加密,JPEG、ASCII
- 会话层:建立,解除会话。主机进程,指本地主机与远程主机正在进行的会话(安全协议SSL、TLS + RPC)
- 传输层:提供端对端的接口,tcp,udp
- 网络层:分配地址,为数据包选择路由,主要协议是IP协议(icmp
- 数据链路层:(传输有地址的帧
- 物理层:(二进制的数据形式在物理媒体上传输数据
TCP三次握手
- 第一次握手:主机A主动去connect主机B,请求数据,并且发送SYN,也就是SYN=1,Seq number序列号为随机int X,等待B确认。客户(主机A)是主动的,服务器(主机B)是被动打开的。
- 第二次握手:主机B在收到SYN后,它会向A发送一个SYN=1 序列号是Y,以及一个ACK=1(应答),ACK number是 X+1表示是给SYN X的应答,
- 第三次握手:主机A在收到新SYN Y, ACK X+1 后,检查ACKnumber是否正确,以及位码ACK=1,也回应ACK Y+1以表示收到了。SYN=0,ACK=1
- 主机B收到后确认后,然后两边就可以开始数据发送数据了
三次握手失败
- 两端都不会申请资源
- 客户端由于没有收到这条响应,不会申请资源,但服务端已经申请了资源。如果迟迟收不到来自客户端的ACK,也会将该资源释放
- 服务端迟迟没有收到ACK,就会释放资源;客户端认为自己已经连接好了,就会给服务端发送数据,服务端由于没有收到第三次握手,就会发RST包,关闭连接
四次挥手
建立连接后,双方都要释放自己的连接
- TCP客户端发送一个FIN,用来关闭客户到服务器的数据传送。
- 服务器收到这个FIN=M,它发回一个ACK=M+1,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号。
- 服务器关闭客户端的连接,发送一个FIN=N给客户端。
- 客户端发回ACK报文确认,并将确认序号ACK=N+1。
TCP和UDP的区别
- TCP是面向连接的协议,在收发数据前,必须和对方建立可靠的连接;udp是无连接的,发送数据前不需要先建立链接。
- TCP是一种可靠性传输。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达,所以适合大数据量的交换; UDP是不可靠的,尽最大努力交付。
- TCP是面向字节流,流模式;UDP面向报文,并且网络出现拥塞不会使得发送速率降低(因此会出现丢包,对实时的应用比如IP电话和视频会议等)。
- TCP只能是1对1的,UDP支持1对1,1对多,因为不需要建立连接。
- TCP的首部较大为20字节,而UDP只有8字节,额外开销很小。
http和https和http2.0
https
https是http的安全版,因为http传输的数据都是未加密的,是明文传输的,这就意味着介于发送端和接收端之间的任意节点都可以知道传输的内容是什么(这些节点可以是路由器、代理等)而https协议是由http和ssl协议(TLS)构建的,能进行加密传输和身份认证的网络协议
- 非对称密钥交换:RSA、ECDHE、DH、DHE等算法
- 缺点: CPU 计算资源消耗非常大 / 加密内容的长度有限制
参考
- 缺点: CPU 计算资源消耗非常大 / 加密内容的长度有限制
- 对称加密:DES\AES
- 单向加密:MD5\SHA\MAC 是不可逆的
加密通信过程 SSL
- 客户端发送SSL版本,随机数和支持的加密算法
- server确定市容的加密协议,服务器证书包括公钥用来加密信息
- 客户端判断证书是否合法,然后会发送一个随机字符串给“服务器”用私钥去加密,服务器把加密的结果返回后,客户端用公钥解密,如果解密结果与之前生成的随机字符串一致,那说明对方确实是私钥的持有者,也就是说对方确实是“服务器”。
- 验证“服务器”的身份后,“客户”生成一个对称加密算法和密钥,用于后面的通信的加密和解密。
参考1
参考2
http1
- 高延迟 — 队头阻塞(Head-Of-Line Blocking)
- 无状态特性 — 阻碍交互
- 明文传输 — 不安全性
- 不支持服务端推送
http2
http2相对于http1.0:
- 提升访问速度:
- 允许多路复用:改善了在同一时间,针对同一域名下的请求有一定数量限制
- 将所有的传输信息分割成更小的信息,并进行二进制编码
- 压缩头部
- 服务器端推送:比如客户端请求主页,服务器响应主页,并响应可能会用到的style或者图片。一次请求,多次响应。
HTTP请求头
Host 域名端口号
Date
Accept Accept-Encoding Accept-Language
Authorization 认证 / 401
Content-Type
origin: / 响应头Access-Control-Allow-Origin跨域
Referer:
User-Agent:浏览器的身份标识字符串
cookie
Cache-Control: 是否使用缓存机制。
If-None-Match / 对应etag
If-Modified-Since / Last-Modified
HTTP响应头
Date
Content-Type
Content-Encoding
Content-Length
Access-Control-Allow-Origin
Cache-Control
etag
Last-Modified
Set-Cookie
Status
fetch发送2次请求的原因
post请求的时候,第一次发送了一个Options请求,询问服务器是否支持修改的请求头,如果服务器支持,则在第二次中发送真正的请求。
http返回状态码
2xx成功
200 OK 请求成功。一般用于GET与POST请求
201 Created 已创建。成功请求并创建了新的资源
202 Accepted 已接受。已经接受请求,但未处理完成
3xx重定向
301 Moved Permanently 永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替
302 Found 临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI
304 Not Modified 未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源
305 Use Proxy 使用代理。
4xx请求出错
400 Bad Request 客户端请求的语法错误,服务器无法理解
401 Unauthorized 请求要求用户的身份认证
403 Forbidden 服务器理解请求客户端的请求,但是拒绝执行此请求
404 Not Found 服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置”您所请求的资源无法找到”的个性页面
5xx
500 Internal Server Error 服务器内部错误,无法完成请求
501 Not Implemented 服务器不支持请求的功能,无法完成请求
502 Bad Gateway 作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应
http请求方式
- get、post,还有patch、delete、put、options等等
- GET - 从指定的资源请求数据。
- POST - 向指定的资源提交要被处理的数据,创建新资源。
- PUT: 更新资源
- Patch: 局部修改资源
- Delete:删除url指定的资源
- Options:请求指定URL所支持的通信
get和post 区别
- GET在浏览器回退时是无害的,而POST会再次提交请求。
- GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
- GET请求会被浏览器主动cache,而POST不会,除非手动设置。
- GET请求在URL中传送的参数长度有限的,而POST么有。
- GET请求只能进行url编码,而POST支持多种编码方式。
- GET比POST更不安全,因为参数直接暴露在URL上,POST在Request Body中。所以GET不能用来传递敏感信息。
- 对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
- GET产生的URL地址可以被Bookmark,而POST不可以。
- ※※ GET产生一个TCP数据包;POST产生两个TCP数据包。
- GET请求:浏览器会把http header和data一并发送出去,服务器响应200(返回数据)
- POST:浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。
浏览器缓存机制:强缓存 和 协商缓存
- 根据响应的header内容来决定
- 强缓存:200 直接从缓存取:
- 当请求再次发出时,浏览器会判断目标资源是否“命中”强缓存,若命中则直接从缓存中获取资源,不会再与服务端发生通信。
- Cache-Control:max-age=300
- Expires 过期时间,(时间戳)
- 协商缓存:304
- 浏览器需要通过服务器来告知缓存是否可用,进而判断是重新发起请求、下载完整的响应,还是从本地获取缓存的资源。如果服务端提示缓存资源未改动(Not Modified),资源会被重定向到浏览器缓存,对应状态码是304。
- ※ Etag和If-None-Match:
- Etag上一次加载资源时,服务器返回的response header;只要资源有变化,Etag就会重新生成,是根据内容编码的
- 将上一次返回的Etag值放到request header里的If-None-Match里;服务器接受到If-None-Match的值后,会拿来跟该资源文件的Etag值做比较,如果相同,则表示资源文件没有发生改变,命中协商缓存。
- ※ Last-Modified和If-Modified-Since(时间戳)
- 放到request headr里的If-Modified-Since里,服务器在接收到后也会做对比,如果相同则命中协商缓存
浏览器缓存位置
- Memory Cache
- 内存中的缓存。浏览器优先去命中的一种缓存,也是响应速度最快的一种缓存。
- 缺点是缓存时间短,关闭tab页面缓存将不复存在
- Disk Cache
- 硬盘缓存。缓存位置在电脑硬盘上,读取速度慢。
- 大体积文件 和 系统内存使用率高的文件
- 所有缓存中,它的覆盖面是最广的,会根据HTTP Header中的字段判断哪一些资源需要缓存,哪些可以不请求直接使用,哪一些已过期需要重新请求。
浏览器会把js和图片等文件解析执行后直接存入内存缓存中,刷新页面时只需直接从内存缓存中读取;css文件则会存入硬盘文件中,所以每次渲染页面都需要从硬盘读取缓存
- Service Worker Cache (只能 https 协议)
- 这是一个独立的线程,能够在不干扰主线程的情况下来提升性能
- 实现离线缓存、消息推送以及网络代理等功能
- 先注册
window.navigator.serviceWorker.register
,监听install事件,下次访问的时候就可以拦截请求来获取缓存数据
- Push Cache
Web攻击
- XSS跨站脚本:嵌入一段危害性的js代码
- 将一些隐私数据像 cookie发送给攻击者,将受害者重定向到一个由攻击者控制的网站
- 防御:对输入(和URL参数)进行过滤,对输出进行编码 / 设置
HttpOnly
属性禁止读取cookie
- CRSF跨站请求伪造:利用Cookie 骗取服务器的信任, 别的站点伪造了一个请求
- 防御:验证 HTTP Referer 字段,判断请求的来源地址 / HTTP 头中自定义属性并验证 比如加入一个随机产生的 token 并在server端验证/ 验证码
参考
- 防御:验证 HTTP Referer 字段,判断请求的来源地址 / HTTP 头中自定义属性并验证 比如加入一个随机产生的 token 并在server端验证/ 验证码
Webpack
简介
- 把依赖的模块转化成可以代表这些包的静态文件, 支持代码分割,模块化
- 是一个模块打包工具,可以使用它管理项目中的模块依赖,并编译输出模块所需的静态文件。它可以很好地管理、打包开发中所用到的HTML,CSS,JavaScript和静态文件(图片,字体)等,让开发更高效。对于不同类型的依赖,webpack有对应的模块加载器,而且会分析模块间的依赖关系,最后合并生成优化的静态资源。
构建过程
- 从entry里配置的module开始递归解析entry依赖的所有module
- 每找到一个module,就会根据配置的loader去找对应的转换规则
- 对module进行转换后,再解析出当前module依赖的module
- 这些模块会以entry为单位分组,一个entry和其所有依赖的module被分到一个组Chunk
- 最后webpack会把所有Chunk转换成文件输出
entry output chunk module
- entry 入口,告诉webpack要使用哪个模块作为构建项目的起点,默认为
./src/index.js
- output 出口,告诉webpack在哪里输出它打包好的代码以及如何命名,默认为
./dist
- module是开发中的单个模块
- loader:
- babel-loader: 将ES6+转移成ES5
- css-loader,style-loader less-loader:解析css文件,能够解释@import url()等
- loader:
- resolve: extension
- devServer: historyApiFallback
Loader
Webpack本身只能处理js模块,如果要处理其他类型的文件,就需要使用 loader 进行转换。一般用作编译预处理器
算法
排序算法
冒泡
- 两个for循环,比较大小,(第一个)比后面的大就交换位置
- 改进:如果有一次没有任何两数进行交换,就将flag设置为 true
1 | function maopao(arr){ |
1 | function maopao (arr) { |
选择
- 两个for循环,每次找到最小的和(第一个)互换位置
1 | function xuanze(arr){ |
插入
- 前面的认为已经被排序,后一个(第二个)在已排序的元素序列中从后向前扫描,比已排序的小就往前
1 | function charu(arr) { |
快排
- 选一个基准,然后重新排序数列,比基准值小的摆放在基准前面,比基准值大的摆在基准的后面,排序后基准就处于中间位置。
1 | function kuaisu(arr){ |