前端面试题整理-持续更新CSS,JS,React,http等
null是对象原型链的终点,null == undefined
-
undefined不是保留字,它只是全局对象的一个属性,在低版本 IE 中能被重写。
-
undefined 在 ES5 中已经是全局对象的一个只读(read-only)属性了,它不能被重写。但是在局部作用域中,还是可以被重写的。
-
void 0 === undefined,用 void 0 代替 undefined 能节省不少字节的大小,事实上,不少 JavaScript 压缩工具在压缩过程中,正是将 undefined 用 void 0 代替掉了。
CSS
position
position: static | relative | absolute | sticky | fixed
-
static: 该关键字指定元素使用正常的布局行为,即元素在文档常规流中当前的布局位置。此时 top, right, bottom, left 和 z-index 属性无效
-
relative: 相对定位的元素是在文档中的正常位置偏移给定的值,但是不影响其他元素的偏移
-
absolute: 相对定位的元素并未脱离文档流,而绝对定位的元素则脱离了文档流。在布置文档流中其它元素时,绝对定位元素不占据空间。绝对定位元素相对于最近的非 static 祖先元素定位
-
sticky: 粘性定位可以被认为是相对定位和固定定位的混合。元素在跨越特定阈值前为相对定位,之后为固定定位
- 粘性定位常用于定位字母列表的头部元素。标示 B 部分开始的头部元素在滚动 A 部分时,始终处于 A 的下方。而在开始滚动 B 部分时,B 的头部会固定在屏幕顶部,直到所有 B 的项均完成滚动后,才被 C 的头部替代
-
fixed: 固定定位与绝对定位相似,但元素的包含块为 viewport 视口。该定位方式常用于创建在滚动屏幕时仍固定在相同位置的元素
animation transition
animation: name | duration | timing-function | delay | iteration-count | direction | fill-mode | play-state
transition: property name | duration | timing function | delay
transition从:hover延伸出来;animation从flash延伸出来
-
不同点
- 触发条件不同。transition通常和hover等事件配合使用,由事件触发,强调过渡。animation则和gif动态图差不多,立即播放,多个关键帧,实现自由动画。
- 循环。 animation可以设定循环次数。
- 精确性。 animation可以设定每一帧的样式和时间。tranistion 只能设定头尾。 animation中可以设置每一帧需要单独变化的样式属性,可以通过@keyframe控制当前帧属性,更灵活, transition中所有样式属性都要一起变化
- 与javascript的交互。animation与js的交互不是很紧密。tranistion和js的结合更强大。js设定要变化的样式,transition负责动画效果。
圣杯布局,双飞翼布局(淘宝UED)
- 三列布局,中间宽度自适应,两边定宽
- 中间栏要在浏览器中优先展示渲染
- 允许任意列的高度最高
区别: 圣杯布局是middle+padding,双飞翼采用子元素+margin,最主要的还是负边距的使用,以及浮动布局和相对定位
因为浏览器渲染引擎在构建和渲染渲染树是异步的(谁先构建好谁先显示),方便SEO
回流,重绘
浏览器使用流式布局模型。浏览器会把HTML解析成DOM,把CSS解析成CSSOM,DOM和CSSOM合并就产生了Render Tree。有了RenderTree,我们就知道了所有节点的样式,然后计算他们在页面上的大小和位置,最后把节点绘制到页面上。由于浏览器使用流式布局,对Render Tree的计算通常只需要遍历一次就可以完成,但table及其内部元素除外,他们可能需要多次计算,通常要花3倍于同等元素的时间,这也是为什么要避免使用table布局的原因之一。回流必将引起重绘,重绘不一定会引起回流
-
当Render Tree中部分或全部元素的尺寸、结构、或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程称为回流,如何引发回流
-
页面首次渲染,浏览器窗口改变大小,元素尺寸或位置发生改变,元素内容变化(文字数量或图片大小等等),元素字体大小变化,DOM操作,激活CSS伪类(例如::hover),查询某些属性或调用某些方法
-
scrollTo(),getComputedStyle(),scrollIntoView()、scrollIntoViewIfNeeded(),getBoundingClientRect()
-
-
当页面中元素样式的改变并不影响它在文档流中的位置时(例如:color、background-color、visibility等),浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘
如何避免
- 避免使用table布局。
- 尽可能在DOM树的最末端改变class
- 避免设置多层内联样式
- 将动画效果应用到position属性为absolute或fixed的元素上。
- 避免使用CSS表达式(例如:calc())
- 避免频繁操作样式,最好一次性重写style属性,或者将样式列表定义为class并一次性更改class属性
- 避免频繁操作DOM,创建一个documentFragment,在它上面应用所有DOM操作,最后再把它添加到文档中
- 先为元素设置display: none,操作结束后再把它显示出来。因为在display属性为none的元素上进行的DOM操作不会引发回流和重绘
- 避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来
- 对具有复杂动画的元素使用绝对定位,使它脱离文档流,否则会引起父元素及后续元素频繁回流
居中
- 水平居中
<!--行内元素:文本text、图像img、按钮超链接等 --> .center { text-align: center; } <div class="center">水平居中</div> <!--块级定宽元素 --> .center { width: 200px; margin: auto; } <div class="center">水平居中</div> <!--块级不定宽元素,table --> .center { display: table; margin: auto; } <div class="center">水平居中</div> <!--块级不定宽元素,inline-block --> .center { text-align: center; >div { display: inline-block; } } <div class="center"><div>inline-block<div></div> <!--块级不定宽元素,flex --> .center { text-align: flex; justify-content: center; } <div class="center"><div>flex<div></div> 复制代码
- 垂直居中
<!--单行文本 line-height=height或者padding-top=padding-bottom--> .colCenter { height: 24px; line-height: 24px; } <div class="colCenter">垂直居中</div> <!--多行文本,利用table --> .colCenter { width: 200px; height: 200px; display: table; >div { display: table-cell; vertical-align: middle; } } <div class="colCenter"><div>垂直居中<div></div> <!--块级元素,flex --> .colCenter { width: 200px; height: 200px; display: flex; align-items: center; } <div class="colCenter"><div>垂直居中<div></div> 复制代码
除此之外,还可以利用padding和margin等计算居中
块格式化上下文(Block Formatting Context,BFC)
是Web页面的可视CSS渲染的一部分,是块盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。触发条件如下:
根元素<html> 浮动元素(元素的 float 不是 none) overflow 值不为 visible 的块元素 display的值为inline-block、table-cell、table-caption position的值为absolute或fixed
作用:清除浮动,浮动塌陷,外边距塌陷
- 自适应两栏布局
- 可以阻止元素被浮动元素覆盖
- 可以包含浮动元素——清除内部浮动
- 分属于不同的BFC时可以阻止margin重叠
canvas和svg的区别,适用场景
-
Canvas提供的功能更原始,适合像素处理,动态渲染和大数据量绘制;Canvas基于像素,提供2D绘制函数,是一种HTML元素类型,依赖于HTML,只能通过脚本绘制图形
- 定制型更强,可以绘制绘制自己想要的东西
- 非dom结构形式,用JavaScript进行绘制,涉及到动画性能较高
- 事件分发由canvas处理,绘制的内容的事件需要自己做处理
- 依赖于像素,无法高效保真,画布较大时候性能较低
- 不支持事件处理器
- 适合游戏应用
-
SVG功能更完善,适合静态图片展示,高保真文档查看和打印的应用场景,不依赖于像素,无限放大后不会失真;SVG为矢量,提供一系列图形元素(Rect, Path, Circle, Line …),还有完整的动画,事件机制,本身就能独立使用,也可以嵌入到HTML中
- 矢量图,不依赖于像素,无限放大后不会失真。
- 以dom的形式表示,事件绑定由浏览器直接分发到节点上
- dom形式,涉及到动画时候需要更新dom,性能较低。
- 支持事件处理器
- 不适合游戏应用 P
JS
数据类型:number,string,null,boolean,undefined,object(Array,Function,RegExp,Date)
类型判断:
-
typeof: 1.基本数据类型除了null返回object,其他都正确;2.引用数据类型,除了function返回function,其他都返回object
-
instanceof: A instanceof B,A是否为B的实例,instanceof 检测的是原型;例如 []. proto——》Array.prototype. proto ——》Object.prototype. proto ——》null
-
constructor: null 和 undefined 是无效的对象,因此是不会有 constructor 存在的,这两种类型的数据需要通过其他方式来判断
-
toString: toString() 是 Object 的原型方法,对于 Object 对象,直接调用 toString() 就能返回 [object Object] 。而对于其他对象,则需要通过 call / apply 来调用才能返回正确的类型信息。用法:Object.prototype.toString.call('')
-
内置Symbol接口
原型链:
-
js分为函数对象和普通对象,每个对象都有__proto__属性,但是只有函数对象才有prototype属性
-
构造函数的__proto__都指向Object.prototype, 因为原型对象本身是普通对象
function F(){}; F.prototype.__proto__ = Object.prototype; Array.prtotype.__proto__ = Object.prototype; Object.prototype.__proto__ = null; F.__proto__ = Function.prototype; var f = new F(); f.__proto__ = F.prototype; 复制代码
call,apply,bind
改变函数执行时的上下文,改变函数运行时的this指向
- bind 是创建一个新的函数,call,apply会执行函数
- 参数不同
map/set,weakMap/weakSet
Set和Map都可以用来生成新的 Map
// 去重,Set接受数组或者类数组为参数 var arr = new Set([1,2,3,2,4]) [...arr] // [1,2,3,4] // WeakSet 中的对象都是弱引用,垃圾回收机制不考虑 WeakSet 对该对象的引用,WeakSet不可遍历 const a = [[1, 2], [3, 4]]; const ws = new WeakSet(a); // WeakSet {[1, 2], [3, 4]} 注意,是a数组的成员成为 WeakSet 的成员,而不是a数组本身。这意味着,数组的成员只能是对象。 const map = new Map([ ['name', '张三'], ['title', 'Author'] ]); map.set('name','jin'); // WeakMap结构与Map结构类似,也是用于生成键值对的集合 // WeakMap只接受对象作为键名(null除外),不接受其他类型的值作为键名;WeakMap的键名所指向的对象,不计入垃圾回收机制,WeakMap 弱引用的只是键名,而不是键值 // 基本上,如果你要往对象上添加数据,又不想干扰垃圾回收机制,就可以使用 WeakMap。一个典型应用场景是,在网页的 DOM 元素上添加数据,就可以使用WeakMap结构。当该 DOM 元素被清除,其所对应的WeakMap记录就会自动被移除。 复制代码
堆栈:
栈内存一般储存基础数据类型,遵循后进先出的原则,大小固定并且有序;堆内存一般储存引用数据类型,JavaScript不允许直接访问堆内存中的位置,因此当我们要访问堆内存中的引用数据类型时,实际上我们首先是从栈中获取了该对象的地址引用(或者地址指针),然后再从堆内存中取得我们需要的数据
-
栈:存储基础数据类型;按值访问;存储的值大小固定;由系统自动分配内存空间;空间小,运行效率高;先进后出,后进先出;栈中的DOM,ajax,setTimeout会依次进入到队列中,当栈中代码执行完毕后,再将队列中的事件放到执行栈中依次执行
-
堆: 存储引用数据类型;按引用访问;存储的值大小不定,可动态调整;主要用来存放对象;空间大,但是运行效率相对较低;无序存储,可根据引用直接获取
执行上下文
- 全局可执行上下文,函数可执行上下文,Eval可执行上下文
执行栈
- 当程序进入执行环境,将执行上下文推入执行栈中(入栈)
- 当程序执行完成之后,执行上下文就会被销毁,并从栈顶被推出(出栈)
eventloop事件循环
"主线程"(执行栈)和任务队列<先进先出>(主要是各种I/O操作)的通信,被称为事件循环
- node环境 还是 浏览器环境
- 任务队列(task queue):分为3,4
- 宏任务task(macro-task):script(整体代码),setTimeout,setInterval,setImmediate,I/O,UI render
- 微任务jobs(micro-task):process.nextTick,Promise,Async/Await(实际就是promise),MutationObserver(html5新特性)
- 事件循环机制:主线程 ->所有微任务 ->宏任务(先进先执行,如果里面有微任务,则下一步先执行微任务,否则继续执行宏任务)
node 11之后的特性已经向浏览器看齐了。两者最主要的区别在于浏览器中的微任务是在每个相应的宏任务中执行的,而nodejs中的微任务是在不同阶段之间执行的
垃圾回收机制
- 引用计数:0引用时会被回收,IE 6, 7 使用引用计数方式对 DOM 对象进行垃圾回收。该方式常常造成对象被循环引用时内存发生泄漏
- 标记-清除算法:这个算法把“对象是否不再需要”简化定义为“对象是否可以获得”,因为“有零引用的对象”总是不可获得的,垃圾回收器将定期从根开始,找所有从根开始引用的对象,对堆内存从头到尾进行线性的遍历,进行标记,而没有被标记的对象就被清除
浅拷贝:遍历对象赋值,只能用作基本数据类型的拷贝
深拷贝:递归浅拷贝
function deepCopy(a,b){ let c = b || {}; for(let i in a){ if(typeof a[i] == 'object'){ c[i] = a[i].constructor === Array ? [] : {}; deepCopy(a[i],c[i]); }else{ c[i] = a[i]; } } return c; } var parent = { name: 'king', animals: { dogs: 2, cat: 1 }, area: ['A','B'] } var obj = deepCopy(parent,{}); 复制代码
json序列化和反序列化的缺点:
new
Person (){ } var obj = new Object(); obj.__proto__ = Person.prototype; Person.call(obj) 复制代码
构造函数和class(语法糖)的区别
-
类的内部所有定义的方法,都是不可枚举的
-
类和模块的内部,默认就是严格模式(this 实际指向的是undefined),非严格模式指向window,所以不需要使用use strict指定运行模式
-
类不存在变量提升(hoist)
-
类的方法内部如果含有this,它默认指向类的实例
-
类的静态方法不会被实例继承,静态方法里的this指的是类,而不是他的实例
-
类的继承extends,在constructor中使用super,让this指向当前类,等同于Parent.prototype.constructor.call(this)
class Parent { constructor(name,age) { this.name = name; this.age = age; } say(){ console.log('hello') } } // 等价于 function Parent(name,age){ this.name = name; this.age = age; } Parent.prototype.say = function (){ console.log('hello'); } var child = new Parent('king',12); 复制代码
类的数据类型就是函数,类本身就指向构造函数;使用的时候,也是直接对类使用new命令,跟构造函数的用法完全一致;Object.assign方法可以很方便地一次向类添加多个方法;prototype对象的constructor属性,直接指向“类”的本身,这与 ES5 的行为是一致的;
function和箭头函数
-
箭头函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象
-
不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误
-
不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替
-
箭头函数不能用作 Generator 函数
-
function可以使this动态使用(比如监听按钮事件,this就会动态指向被点击的按钮对象),如果函数体内有大量的读写操作,尽量不要使用箭头函数
手动实现字符串单词统计,’sdsdfdewrwescvv’,统计各个出现次数
var str = 'sdsdfdewrwescvv'; let obj = {}; for (i = 0; i<str.length; i++){ if(obj[str[i]]){ obj[str[i]]++; }else{ obj[str[i]] = 1; } } console.log(obj); 复制代码
promise,generator,async/await 对比
promise手动实现
1. 设置三种状态,一但开始不能暂停,且状态只能被修改一次,pending,rejected,resolved(fulfilled) 2. 两个参数,resolve(),reject(),函数执行之后改变状态,执行的时候如果传递参数,就是then的参数 3. 回调函数,then(resolved,rejected(可选)),返回新promise实例,以便继续链式调用,注意是异步操作,可以使用settimeout 4. catch异常回调,Promise.prototype.catch()方法是.then(null, rejection)或.then(undefined, rejection)的别名,用于指定发生错误时的回调函数。 复制代码
用async/await实现promise.all
1. promise.all的参数数组里面的promise,如果自己定义了catch方法,那么它一旦被rejected,并不会触发Promise.all()的catch方法 2. 参数数组里面的实例只要有一个变为rejected,或者都为fulfilled,就会调用回调函数 3. async函数返回的 Promise 对象,必须等到内部所有await命令后面的 Promise 对象执行完,才会发生状态改变,除非遇到return语句或者抛出错误。也就是说,只有async函数内部的异步操作执行完,才会执行then方法指定的回调函数 复制代码
在await之后增加手动判断,抛出异常
es 6 module和cmd中的模块require有什么区别
- Require是CommonJS的语法
- export后面要跟能够解构的对象,export 命令规定的是对外接口,必须与模块内部变量建立一一对应的关系
- require是动态加载的,import是编译的时候加载的
继承
- 原型链继承
function Parent(){ this.color = ['red','yellow'] } function child() {} child.prototype = new Parent(); var eg1 = new child(); eg1.color.push('white'); var eg2 = new child(); console.log(eg2) // ["red", "yellow", "white"] 原型链方案存在的缺点:多个实例对引用类型的操作会被篡改 复制代码
- 构造函数继承
function Person(){ this.color = ['red','yellow'] } Person.prototype.say=function(){ console.log('hi') } function child(){ Person.call(this); } var eg1 = new child(); eg1.color.push('white'); console.log(eg1.say) // undefined var eg2 = new child(); console.log(eg2) // ["red", "yellow"] 比前一种更耗内存,影响性能,每次都要执行建立Person实例 不能继承原型方法 复制代码
- 组合继承
把前两种组合一下 function Person(){ this.age = 11; this.color = ['red','yellow'] } Person.prototype.say=function(){ console.log('hi') } function child(){ Person.call(this); } child.prototype = new Parent(); child.prototype.constructor = child; var eg1 = new child(); eg1同时继承child 和person 缺点: 子类实例中会存在两份相同的属性/方法 复制代码
- 原型式继承
即后来的Object.create内置函数,其原理为 function Person(o){ var child = function(){}; child.prototype = o; return new child(); } 复制代码
但实际上new具体做了什么操作
var son = new Person(); 复制代码
当这段代码运行的时候,内部实际上执行的是:
// 创建一个空对象 var other = new Object(); // 将空对象的原型赋值为构造函数的原型 other.__proto__ = Person.prototype; // 改变this指向 Person.call(other); 复制代码
缓存 SessionStorage,localStorage,Cookie
存储方式
- cookie会数据始终在同源http请求中携带,在浏览器和服务器之间来回传递
- sessionStroage和localStroage仅保存在本地
存储大小
- 单个cookie不能超过4K,很多浏览器都限制一个站点最多保存20个Cookie
- sessionStroage和localStroage可以达到5M
过期时间
- 只在设置的cookie过期时间之前有效,即使窗口关闭或浏览器关闭
- sessionStorage,仅在当前浏览器窗口关闭之前有效
- localStorage:始终有效,窗口或浏览器关闭也一直保存,本地存储,因此用作持久数据
作用域
- cookie和localStorage: 在所有同源窗口中都是共享的.只要浏览器不关闭,数据仍然存在
- sessionStorage:打开多个相同的URL的Tabs页面,会创建各自的sessionStorage;关闭对应浏览器tab,会清除对应的sessionStorage
节流和防抖
-
节流: 每隔一段时间,只执行一次函数
-
防抖: 连续的事件,只需触发一次回调
设计模式,观察者,发布订阅模式
- 主要是消息的处理机制不同,一个同步一个异步,而异步的实现手段是使用MQ,类似于Kafka
跨域
- 同源:协议+域名+端口都一样;当协议、子域名、主域名、端口号中任意一个不相同时,都算作不同域。不同域之间相互请求资源,就算作“跨域”
- 如果是协议和端口造成的跨域问题“前台”是无能为力的
- 跨域并不是请求发不出去,请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了
http
概念:超文本传输协议(HTTP)是一个用于传输超媒体文档(例如 HTML)的应用层协议。它是为 Web 浏览器与 Web 服务器之间的通信而设计的,但也可以用于其他目的。HTTP 遵循经典的客户端-服务端模型,客户端打开一个连接以发出请求,然后等待它收到服务器端响应。HTTP 是无状态协议,这意味着服务器不会在两个请求之间保留任何数据(状态)。该协议虽然通常基于 TCP/IP 层,但可以在任何可靠的传输层上使用;也就是说,不像 UDP,它是一个不会静默丢失消息的协议。RUDP——作为 UDP 的可靠化升级版本——是一种合适的替代选择
http特性:
1.HTTP 是无连接无状态的
2.HTTP 一般构建于 TCP/IP 协议之上,默认端口号是 80
3.HTTP 可以分为两个部分,即请求和响应。
HTTP各版本特性及区别
1.http0.9– 单行协议:请求由单行指令构成,以唯一可用方法GET开头,其后跟目标资源的路径(一旦连接到服务器,协议、服务器、端口号这些都不是必须的);响应也极其简单的:只包含响应文档本身。
2.http1.0:协议版本信息现在会随着每个请求发送(HTTP/1.0被追加到了GET行);状态码会在响应开始时发送;引入了HTTP头的概念;Content-Type让请求具备了传输除纯文本HTML文件以外其他类型文档的能力
3.http1.1:连接可以复用,节省了多次打开TCP连接加载网页文档资源的时间;增加管线化技术,允许在第一个应答被完全发送之前就发送第二个请求,以降低通信延迟;支持响应分块;引入额外的缓存控制机制;引入内容协商机制,包括语言,编码,类型等,并允许客户端和服务器之间约定以最合适的内容进行交换;感谢Host头,能够使不同域名配置在同一个IP地址的服务器上
4.http2.0:HTTP/2是二进制协议而不是文本协议。不再可读,也不可无障碍的手动创建,改善的优化技术现在可被实施;这是一个复用协议。并行的请求能在同一个链接中处理,移除了HTTP/1.x中顺序和阻塞的约束;压缩了headers。因为headers在一系列请求中常常是相似的,其移除了重复和传输重复数据的成本;其允许服务器在客户端缓存中填充数据,通过一个叫服务器推送的机制来提前请求
5.http3.0: 将弃用TCP协议,改为使用基于UDP协议的QUIC协议实现,该协议旨在使网页传输更快
TCP,UDP
- 基于连接与无连接
- 对系统资源的要求(TCP较多,UDP少)
- UDP程序结构较简单
- 流模式与数据报模式
- TCP保证数据正确性,UDP可能丢包;
- TCP保证数据顺序,UDP不保证。
http请求:
-
HTTP 请求由 3 个部分构成,分别是:状态行,请求头(Request Header),请求正文。
-
HTTP 响应由 3 个部分构成,分别是:状态行,响应头(Response Header),响应正文。
-
HTTP 响应中包含一个状态码,用来表示服务器对客户端响应的结果。 状态码一般由3位构成:
1xx : 表示请求已经接受了,继续处理。 2xx : 表示请求已经处理掉了。 3xx : 重定向。 4xx : 一般表示客户端有错误,请求无法实现。 5xx : 一般为服务器端的错误。
- get:GET方法请求一个指定资源的表示形式. 使用GET的请求应该只被用于获取数据.
- post:POST方法用于将实体提交到指定的资源,通常导致在服务器上的状态变化或副作用
- head: HEAD方法请求一个与GET请求的响应相同的响应,但没有响应体.
- put:PUT方法用请求有效载荷替换目标资源的所有当前表示。
- delete:DELETE方法删除指定的资源。
- connect:CONNECT方法建立一个到由目标资源标识的服务器的隧道
- options:OPTIONS方法用于描述目标资源的通信选项
- trace:TRACE方法沿着到目标资源的路径执行一个消息环回测试。
- patch:PATCH方法用于对资源应用部分修改
常见的状态码:
-
200 OK 客户端请求成功。
-
301 Moved Permanently 请求永久重定向。
-
302 Moved Temporarily 请求临时重定向。
-
304 Not Modified 文件未修改,可以直接使用缓存的文件。
-
400 Bad Request 由于客户端请求有语法错误,不能被服务器所理解。
-
401 Unauthorized 请求未经授权,无法访问。
-
403 Forbidden 服务器收到请求,但是拒绝提供服务。服务器通常会在响应正文中给出不提供服务的原因。
-
404 Not Found 请求的资源不存在,比如输入了错误的URL。
-
500 Internal Server Error 服务器发生不可预期的错误,导致无法完成客户端的请求。
-
502 Bad Gateway 是一种HTTP协议的服务器端错误状态代码,它表示作为网关或代理角色的服务器,从上游服务器(如tomcat、php-fpm)中接收到的响应是无效的
-
503 Service Unavailable 服务器当前不能够处理客户端的请求,在一段时间之后,服务器可能会恢复正常。
http与https的区别
- https协议需要到ca申请证书,一般免费证书较少,需要付费
- http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议
- http默认80端口,https默认443端口
- http是无状态连接;https协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,安全性更高
对称加密,非对称加密
- 对称加密:一般小于256bit,密钥越大,加密越强,但是加密与解密的时间越长;加密与解密用的是同样的密钥;缺点:密钥的管理和分配
- 非对称加密:最常用的非对称加密算法是RSA算法;通过一堆密钥:公钥和私钥,私钥由一方安全保管,公钥可以发送给任何请求他的人,只有私钥才能解密,而且不需要将私钥通过网络发送出去,大大提高网络安全性
在浏览器地址栏输入URL之后回车的过程
-
URL解析,抽出域名字段
-
DNS解析,域名解析成IP
- 浏览器缓存->操作系统缓存->路由器缓存->ISP缓存->根域名服务器->主域名服务器
-
TCP/IP连接,三次握手(Three-way Handshake,是指建立一个 TCP 连接时,需要客户端和服务器总共发送3个包)
-
客户端发送一个 TCP 的 SYN 标志位置1的包,指明客户端打算连接的服务器的端口,以及初始序号 X,保存在包头的序列号(Sequence Number)字段里
-
服务器发回确认包(ACK)应答
-
客户端再次发送确认包(ACK),SYN 标志位为0,ACK 标志位为1,并且把服务器发来 ACK 的序号字段+1,放在确定字段中发送给对方,并且在数据段放写ISN的+1
-
-
发送HTTP请求
-
服务器处理请求并返回 HTTP 报文
-
浏览器解析渲染页面
-
断开连接:TCP 四次挥手
-
假设客户端想要关闭连接,客户端发送一个 FIN 标志位置为1的包,表示自己已经没有数据可以发送了,但是仍然可以接受数据
-
服务器端确认客户端的 FIN 包,发送一个确认包,表明自己接受到了客户端关闭连接的请求,但还没有准备好关闭连接
-
服务器端准备好关闭连接时,向客户端发送结束连接请求,FIN 置为1。发送完毕后,服务器端进入 LAST_ACK 状态,等待来自客户端的最后一个ACK
-
客户端接收到来自服务器端的关闭请求,发送一个确认包,并进入 TIME_WAIT状态,等待可能出现的要求重传的 ACK 包。服务器端接收到这个确认包之后,关闭连接,进入 CLOSED 状态
-
ajax和fetch区别
- ajax本质是利用XMLHttpRequest来实现,fetch采用了Promise的异步处理机制
cdn原理
负载均衡,缓存,dns解析
- 通过dns解析到全局负载均衡服务器,然后再到区域的负载均衡,之后根据一些条件来找合适的缓存服务器,如果第一次访问就从源站拿过来缓存。需要注意的是一切都是根据请求的ip来的,如果ip不合理,那么可能起不到加速效果。缓存和负载均衡的思想在减轻服务器压力方面其实是很常见的
浏览器缓存策略
-
浏览器在加载资源时,根据请求头的expires和cache-control判断是否命中强缓存,是则直接从缓存读取资源,不会发请求到服务器
-
如果没有命中强缓存,浏览器一定会发送一个请求到服务器,通过last-modified和etag验证资源是否命中协商缓存,如果命中,服务器会将这个请求返回,但是不会返回这个资源的数据,依然是从缓存中读取资源
-
如果前面两者都没有命中,直接从服务器加载资源
如果命中,都是从客户端缓存中加载资源,而不是从服务器加载资源数据;强缓存不发请求到服务器,协商缓存会发请求到服务器
react生命周期变更,以及使用方式;为什么变化,为什么取消了那几个生命周期
v16.3去掉componentWillMount,componentWillReceiveProps,componentWillUpdate;新增static getDerivedStateFromProps(props, state),getSnapshotBeforeUpdate(prevProps, prevState)
-
生命周期:set props & state --> componentWillMount(static getDerivedStateFromProps) --> render -->(getSnapshotBeforeUpdate)--> componentDidMount
-
propsUpdate:componentWillReceiveProps(static getDerivedStateFromProps) --> shouldComponentUpdate --> componentWillUpdate(去掉) --> render --> (getSnapshotBeforeUpdate)--> componentDidUpdate(prevProps, prevState, snapshot)
-
stateUpdate:shouldComponentUpdate --> componentWillUpdate(getSnapshotBeforeUpdate) --> render --> componentDidUpdate(prevProps, prevState, snapshot)
-
销毁:componentWillUnmount
-
错误处理: 当渲染过程,生命周期,或子组件的构造函数中抛出错误时,componentDidCatch,static getDerivedStateFromError()
-
componentWillMount是在组件挂载之前调用,在此方法中调用setstate是不会触发render的,如果是初始化数据尽量写在constructor中,如果是请求数据,建议放在componentDidMount中
-
componentWillReceiveProps:容易导致父子组件陷入死循环渲染,
-
componentWillUpdate:因为props更新而引起多次调用,而componentDidUpdate就只会被调用一次
-
getDerivedStateFromProps 会在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用。它应返回一个对象来更新 state,如果返回 null 则不更新任何内容。
- getSnapshotBeforeUpdate() 在最近一次渲染输出(提交到 DOM 节点)之前调用。它使得组件能在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置)。此生命周期的任何返回值将作为参数传递给 componentDidUpdate()。此用法并不常见,但它可能出现在 UI 处理中,如需要以特殊方式处理滚动位置的聊天线程等