面试知识点总结

面试总结

一、HTML+CSS

1.盒模型

标准盒模型:content+padding+border+margin 内容区:content(width 属性==content 的宽度)

怪异盒模型:content+padding+border 内容区:content+padding(width 属性== content+padding+border 的宽度)

2.如何让元素水平垂直居中(最多问到)

1.定位偏移 top、left 为 50%,margin-left、margin-top 为小元素的-50%

2.定位平均 top、left、bottom、right 为 0,margin 为 auto

3.定位平移 top、left 为 50%,transform:translate(小元素的 50%)

4.弹性盒 主轴与交叉轴居中

5.表格 父 display: table-cell、text-align: center、vertical-align: center ,子元素 display: inline-block

3.flex 的几个默认属性

问三个答划线三个: 第一个值为默认值

设置主轴方向:flex-direction: row 横 | row-reverse | column | column-reverse

是否自动换行:flex-wrap: nowrap 不换行 | wrap | wrap-reverse

主轴对齐方式:justify-content: flex-start 左或上 | flex-end | center |space-between | space-around

交叉轴对齐方式:align-items: stretch 高度不设置则占满 | flex-start | flex-end | center | baseline

flex-shrink: 默认 1,空间不足按比缩小,设为 0 不缩小

flex-basis: 默认 auto,占据主轴多少空间

flex-grow:默认为 0,属性定义项目的放大比例,即如果存在剩余空间,也不放大。

flex: 0 1 auto //flex-grow flex-shrink flex-basis

二、原生 JS

1、js的new操作符做了哪些事情?

new 操作符新建了一个空对象,这个对象原型指向构造函数的prototype,然后执行构造函数返回这个对象。
在这里插入图片描述

2、箭头函数可以new进行实例化吗?

箭头函数不可以使用new实例化的,这是因为因为箭头函数没有prototype,arguments也没有自己的this指向。

2、数组 API

pop 删除最后一个元素,原数组;

shift 删除第一个元素,原数组;

push 添加一个新元素在最后,原数组;

unshift 添加一个新元素到第一个位置,原数组;

reverse 颠倒数组,原数组;

slice 截取片段,新数组;

splice(万能的),原数组;

split 用特定字符分割字符串成数组; ‘1$2 3 ′ . s p l i t ( ′ 3'.split(' 3.split(’)==>[‘1’,‘2’,‘3’]

join 用特定字符拼接数组成字符串;[1,2,3].join(’&’)==> ‘1&2&3’

sort 特定顺序排序,原数组;

fill 填充一些变量到指定位置,原数组;

set 数组去重,原数组;

tolocatestring 将时间对象转换为字符串格式;

cancat 数组最后加元素,新数组;

indexof 查找数组里的特定元素,返回索引或-1;

lastindexof 倒序查找;includes 返回数组是否包含某个元素;

foreach 遍历,执行回调;every 检测每个元素符不符合条件;

some 检测有没有元素符合条件;filter 返回过滤后的新数组;

map 返回每个都被操作过的元素组成的新数组;

reduce 归并;

find 返回第一个满足条件的元素;

findindex 返回满足条件的元素的索引

深浅拷贝深拷贝的循环引用

对象的某个属性,正是这个对象本身,此时我们如果进行深拷贝,可能会在子元素->父对象->子元素…这个循环中一直进行,导致栈溢出,造成了循环引用
解决办法就是判断一个对象的字读是否引用了这个对象或者这个对象的任意父级即可

function isObject(obj){
    return Object.prototype.toString.call(obj) === '[object Object]'  || Object.prototype.toString.call(obj) === '[object Array]'
  }
  //使用Map函数
  function deepCopy(obj, map = new Map()) {
    if (!isObject(obj)) return
    var newObj = Array.isArray(obj) ? [] : {}
    if (map.get(obj)) {
      return map.get(obj);
    }
    map.set(obj, newObj);
    for (var key in obj) {
      if (obj.hasOwnProperty(key)) {
        if (isObject(obj[key])) {
          newObj[key] = deepCopy(obj[key], map);
        } else {
          newObj[key] = obj[key];
        }
      }
    }
    return newObj;
  }

AST

抽象语法树(Abstract Syntax Tree),是将代码逐字母解析成树状对象的形式。这是语言之间的转换、代码语法检查,代码风格检查,代码格式化,代码高亮,代码错误提示,代码自动补全等等的基础。例如:

    function square(n){
        return n * n
    }

通过解析转化成的AST如下:

    -FunctionDeclaration{
        type:'FunctionDeclaration'
        start:0
        end:35
        id:Identifier {type,start,end,name}
        expression:false
        generator:false
        params:[1 element]
        body:BlockStatement {type,start,end,body}
    }

babel编译原理

  • babylon将ES6/ES7代码解析成AST(抽象语法树)
  • babel-traverser对AST进行遍历转译,得到新的AST
  • 新AST通过babel-generator转换成ES5

1、数据类型有哪几种, 检测方法是什么??

数据类型共 7 种(不考虑谷歌 67 版本中的 bigInt)
基本数据类型 5 种
ES5-------Number(包含 NaN)、Boolean、String、Undefined、Null
ES6 新增—Symbol
引用数据类型
Object
检测方法 4 种

1、Object.prototype.toString.call()

作用: 可以检测所有数据类型
所有数据类型都可以检测,而且非常正确
语法: Object.prototype.toString.call( ‘xxx’/11/[ ] )
返回值: [object Xxx], Xxx 就是对象的类型

2、constructor

作用: 可以检测 基本数据类型 和 引用数据类型
弊端: 把类的原型进行重写, 很有可能把之前的 constructor 覆盖 检测出来的结果就会不准确
语法: (“xx”)/([ ])/(function(){ }).constructor === String/Array/Function
返回值: true/false

3、instanceOf

原理: 判断对象类型,基于原型链去判断(obj instanceof Object)
左边对象的原型链 proto 上是否有右边构造函数的 proptotype 属性
作用: 判断左边的对象是否是右边构造函数的实例
弊端: 用于引用类型的检测, 对于基本数据类型不生效
语法: " "/[ ]/true instanceOf String/Array/Boolean
返回值: true/false

4、typeOf
!!! typeof null ==> ‘object’
!!! typeof undefined ==> ‘undefined’
作用: 用于检测 基本数据类型 和 函数
弊端: 引用数据类型(Arrary/function/object)只会返回 object, 不起作用
语法: typeOf 123 / ‘number’
返回值: “string”/“boolean”/“object” (无法区分)

2、mouseover和mouseenter的区别

mouseover:当鼠标移入元素或其子元素都会触发事件,所以有一个重复触发,冒泡的过程。对应的移除事件是mouseout

mouseenter:当鼠标移除元素本身(不包含元素的子元素)会触发事件,也就是不会冒泡,对应的移除事件是mouseleave

3、如何让事件先冒泡后捕获

在DOM标准事件模型中,是先捕获后冒泡。但是如果要实现先冒泡后捕获的效果,对于同一个事件,监听捕获和冒泡,分别对应相应的处理函数,监听到捕获事件,先暂缓执行,直到冒泡事件被捕获后再执行捕获事件。

333、commonjs与ES module的区别?

4、事件委托

简介:事件委托指的是,不在事件的发生地(直接dom)上设置监听函数,而是在其父元素上设置监听函数,通过事件冒泡,父元素可以监听到子元素上事件的触发,通过判断事件发生元素DOM的类型,来做出不同的响应。

举例:最经典的就是ul和li标签的事件监听,比如我们在添加事件时候,采用事件委托机制,不会在li标签上直接添加,而是在ul父元素上添加。

好处:比较合适动态元素的绑定,新添加的子元素也会有监听函数,也可以有事件触发机制

if(target.nodeName.toLowerCase() == 'li'){
    alert(target.innerHTML);
}
addEventListener:

addEventListener 是DOM2 级事件新增的指定事件处理程序的操作,这个方法接收3个参数:要处理的事件名、作为事件处理程序的函数和一个布尔值。最后这个布尔值参数如果是true,表示在捕获阶段调用事件处理程序;如果是false(默认值),表示在冒泡阶段调用事件处理程序。

5、get与post

误区:我们经常说get请求参数的大小存在限制,而post请求的参数大小是无限制的。
实际上HTTP 协议从未规定 GET/POST 的请求长度限制是多少。对get请求参数的限制是来源与浏览器或web服务器,浏览器或web服务器限制了url的长度。为了明确这个概念,我们必须再次强调下面几点:

  • HTTP 协议 未规定 GET 和POST的长度限制
  • GET的最大长度显示是因为 浏览器和 web服务器限制了 URI的长度
  • 不同的浏览器和WEB服务器,限制的最大长度不一样
  • 要支持IE,则最大长度为2083byte,若只支持Chrome,则最大长度 8182byte
缓存方面的区别:
  • get请求类似于查找的过程,用户获取数据,可以不用每次都与数据库连接,所以可以使用缓存。
  • post不同,post做的一般是修改和删除的工作,所以必须与数据库交互,所以不能使用缓存。因此get请求适合于请求缓存。

6、图片的懒加载和预加载

  • 预加载:提前加载图片,当用户需要查看时可直接从本地缓存中渲染。
  • 懒加载:懒加载的主要目的是作为服务器前端的优化,减少请求数或延迟请求数。

两种技术的本质:两者的行为是相反的,一个是提前加载,一个是迟缓甚至不加载。
懒加载对服务器前端有一定的缓解压力作用,预加载则会增加服务器前端压力。

7、TCP网络模型属于哪一层

传输层

8、https加密

9、为什么不用index作为key值

如果用index的话追加在后面不会影响,如果追加到前面会 影响性能

99、object.create方法

Object.create方法指定的第1个参数为新建对象的原型对象

98、ES6 Set Map

Set 是一个可以存储无重复的列表
Map 可以存放键值对,键可以对象,函数等

100、webpack基本工作流程:

  1. 初始化参数:从配置文件和Shell语句中读取与合并参数,得出最终参数
  2. 用上一步得到的参数初始化Compiler对象,加载所有的配置插件,执行对象的run方法开始执行编译,确定入口文件
  3. 从入口文件出发,通过fs读模块,调用所有配置的loader对模块进行编译,在找出模块依赖的模块,递归处理
  4. 每个文件生成一个module模块,里面包含经过loader编译后的源代码,然后根据入口和模块之间的依赖关系,组装成一个个包含多个module的chunk,多个chunk组成一个文件,加入到输出列表
  5. 根据配置确定输出的路径和文件名,把文件内容写入到文件系统

//在以上过程中,会在特定的时间点广播出特定事件,插件再监听到感兴趣的事件后会执行特定的逻辑,并且可以调用webpack提供的api改变运行结果

module、chunk、file之间的关系
多个module模块组成chunk代码块,多个chunk组成file文件,文件写入硬盘

10、webpack的plugin和loader区别、热更新原理

loader原理:
抽象语法树(Abstract Syntax Tree),是将代码逐字母解析成树状对象的形式。这是语言之间的转换、代码语法检查,代码风格检查,代码格式化,代码高亮,代码错误提示,代码自动补全等等的基础

  1. babylon将ES6/ES7代码解析成AST(抽象语法树)
  2. babel-traverser对AST进行遍历转译,得到新的AST
  3. 新AST通过babel-generator转换成ES5

10、webpack的tree-shaking

是一种通过清除多余代码的方式来减小打包体积的技术
在webpack编译阶段去除那些只读不写的或者不被执行的代码
webpack 的 tree shaking 依赖于 babel编译 + UglifyJS 压缩

利用的是ES6模块的特点:

  1. 只能作为模块顶层语句出现
  2. import的模块名只能是字符串常量,不能动态引入
  3. import的binding是immutable,引入的模块不能再作修改

tree-shaking不支持动态导入,只支持纯静态导入;
webpack中可以在项目package.json文件中,添加一个sideEffect属性,用于手动指定副作用的脚本。有副作用的就需要保留

11、redux与mobx的区别

1. Redux理想的是immutable的,每次都返回一个新的数据,而Mobx从始至终都是一份引用。因此Redux是支持数据回溯的
2. 然而和Redux相比,使用Mobx的组件可以做到精确更新,这一点得益于Mobx的observable;对应的,Redux是用dispath进行广播,通过Provider和connect来比对前后差别控制更新粒度,有时需要自己写SCU;Mobx更加精细一点。

11、reducer为啥是同步的纯函数且必须要返回一个新的state,返回老的不行?那为什么redux要这样设计呢?

  1. 纯函数是为了确保返回的state是一个确定的值,同一个输入必定返回同一个输出
  2. 返回新的state是因为redux源码中,对新老state进行的是浅比较,比较的是存储位置,所以返回老的state,redux会认为没有改变,从而不刷新页面
  3. 这样设计的原因是因为比较js对象中所有属性是否完全相同的唯一办法就是深比较,而深比较的是非常耗性能的,所以规定开发者一定要返回一个新的对象

12、前端性能优化

13、虚拟DOM virtual DOM

所谓的虚拟 dom,也就是虚拟节点。它通过JS的Object对象模拟DOM中的节点,然后再通过特定的render方法将其渲染成真实的DOM节点
	他是用js模拟一颗dom树,放在浏览器内存中。当你要变更时,虚拟dom使用diff算法进行新旧虚拟dom的比较,生成补丁对象,patch对象渲染到页面中改变的结构上,而其他没有改变的地方是不做任何修改的(虚拟dom的惰性原则)
	2.虚拟dom的使用基本流程(前四步骤)
	1.获取数据
	2.创建虚拟dom
	3.通过render函数解析jsx,将其转换成虚拟dom结构
	4.将虚拟dom渲染成真实dom
	5.数据更改了
	6.使用diff算法比对两次虚拟dom,生成patch对象
	7.根据key将patch对象渲染到页面中改变的结构上,而其他没有改变的地方是不做任何修改的(虚拟dom的惰性原则)
优点:
1、保证性能下限: 
	框架的虚拟 DOM 需要适配任何上层 API 可能产生的操作,它的一些 DOM 操作的实现必须是普适的,所以它的性能并不是最优的;但是比起粗暴的 DOM 操作性能要好很多,因此框架的虚拟 DOM 至少可以保证在你不需要手动优化的情况下,依然可以提供还不错的性能,即保证性能的下限;
2、无需手动操作 DOM: 
	我们不再需要手动去操作 DOM,只需要写好 View-Model 的代码逻辑,框架会根据虚拟 DOM 和 数据双向绑定,帮我们以可预期的方式更新视图,极大提高我们的开发效率;
3、跨平台: 
	虚拟 DOM 本质上是 JavaScript 对象,而 DOM 与平台强相关,相比之下虚拟 DOM 可以进行更方便地跨平台操作,例如服务器渲染等等。

缺点:
无法进行极致优化: 
虽然虚拟 DOM + 合理的优化,足以应对绝大部分应用的性能需求,但在一些性能要求极高的应用中虚拟 DOM 无法进行针对性的极致优化。首次渲染大量DOM时,由于多了一层虚拟DOM的计算,会比innerHTML插入慢。

14、Diff算法

 Diff算法是用于比较两个新旧vdom树的差异的,比较完之后会得到一个差异对象,我们称之为patch补丁对象
1.把树形结构按照层级分解,只比较同级元素。
2.只匹配class类名相同的组件,进行对比。
3.通过给列表结构的每一个元素添加唯一的key值进行区分同层次的子节点比较。
4.选择性渲染。

比较后会出现四种情况:
1、此节点是否被移除 -> 添加新的节点
2、属性是否被改变 -> 旧属性改为新属性
3、文本内容被改变-> 旧内容改为新内容
4、节点要被整个替换 -> 结构完全不相同 移除整个替换


diff算法结束后,返回一个补丁对象(patch)

15、useCallback useMemo

  1. useCallback(fn, deps) 相当于 useMemo(() => fn, deps)。
  2. useCallback会返回一个传递的回调函数的memoized版本
  3. useMemo会返回一个 memoized 值。在依赖没有改变的时候useMemo 会跳过二次调用,只是简单复用它上一次返回的值。

15、react数据流

React遵循从上到下的数据流向,即单向数据流。

单向数据流并非‘单向绑定’,甚至单向数据流与绑定没有‘任何关系’。
对于React来说,单向数据流(从上到下)与单一数据源这两个原则,

限定了React中要想在一个组件中更新另一个组件的状态(类似于Vue的平行组件传参,或者是子组件向父组件传递参数)
,需要进行状态提升。即将状态提升到他们最近的祖先组件中。

子组件中Change了状态,触发父组件状态的变更,父组件状态的变更,
影响到了另一个组件的显示(因为传递给另一个组件的状态变化了,这一点与Vue子组件的$emit()方法很相似)。

16、react的props与state的区别

props:
一般用于父组件向子组件通信,在组件之间通信使用。
state: 
一般用于组件内部的状态维护,更新组建内部的数据,状态,更新子组件的props等。

17、vue和react的区别

1.React严格上是MVC的View层,Vue则是MVVM模式
2.在virtual DOM上不一样,vue会跟踪每一个组件的依赖关系,不需要重新渲染这个组件树,而对于React而言,每当应用状态被改变时,全部组件都会重新渲染,所以react中会需要shouldComponentUpdate这个生命周期来进行优化

18、DVA与CRA相比的优点/umi

dva: dva 首先是一个基于 redux 和 redux-saga 的数据流方案,然后为了简化开发体验,dva 还额外内置了 react-router 和 fetch,所以也可以理解为一个轻量级的应用框架。--- 来自官方。相比于cra只是多了内置的redux和redux-saga,帮我们处理了数据流这方面的需求而已。如果只是想要达到这个效果的话,直接在cra中增加dva-core的依赖也是可以做到的。

umi:是一个可插拔的企业级 react 应用框架。umi和cra都是应用框架,可能相比cra来说umi的功能点更多一些,功能性的话umi要相对来说更胜一筹

19、class中super作用是什么

es5 的继承是先创建子类的this,然后将父类的方法添加到子类的this上去; 
es6 的继承是创建父类的this对象,然后再对this对象添加方法/属性。 
而super方法就是用来创建父类this对象的。
实际上执行的是 super.sport.call(this); 

20、react的class组件,没有class的时候怎么写

React.createClass    
我们最早使用这个方法来构建一个组件“类”,它接受一个对象为参数,
对象中必须声明一个render方法,render返回一个组件实例
var HelloMessage = React.createClass({
    render: function() {
                        return <h1>Hello {this.props.name}</h1>;
                        }
});

21、组件

1、类组件和函数组件
1.类组件中可以使用局部状态state和生命周期
2.函数组件中没有this,没有声明周期,没有状态state
3.函数组件都是展示型组件,接收props,渲染DOM
4.函数组件中没有this
5.函数组件的性能要比类组件高,因为类组件使用时需要实例化,而函数组件直接执行返回结果即可
2、react中的受控组件和非受控组件
受控组件
	HTML中的表单元素是可输入的,也就是有自己的可变状态
	React讲state与表单元素值value绑定在一起,由state的值来控制表单元素的值
	值受到react控制的表单元素
	
非受控组件
	调用 React.createRef() 方法创建ref对象
	将创建好的 ref 对象添加到文本框中
	通过ref对象获取到文本框的值
	简单来说,表单组件没有value prop就可以称为非受控组件
3、 跨组件通信的实现方式
1、可以通过context对象 首先利用createContext创造一个context 在组件中引入这个context就可使用了
2、 redux
3、找到两者组件中最近的父组件,通过,子父通信+父子组件通信,一层一层传递,当层级深时不建议使用
5、Component 跟PureComponent的区别

区别详解

React.PureComponent 与 React.Component 几乎完全相同,但 React.PureComponent 通过props和state的浅对比来实现 shouldComponentUpate()。
 如果React组件的 render() 函数在给定相同的props和state下渲染为相同的结果,在某些场景下你可以使用 React.PureComponent 来提升性能。
  React.PureComponent 的 shouldComponentUpdate() 只会对对象进行浅对比。如果对象包含复杂的数据结构,它可能会因深层的数据不一致而产生错误的否定判断(表现为对象深层的数据已改变视图却没有更新, 原文:false-negatives)。当你期望只拥有简单的props和state时,才去继承 PureComponent ,或者在你知道深层的数据结构已经发生改变时使用 forceUpate() 。或者,考虑使用 不可变对象 来促进嵌套数据的快速比较。
  此外,React.PureComponent 的 shouldComponentUpate() 会忽略整个组件的子级。请确保所有的子级组件也是”Pure”的。
  
PureComponent的作用:
	PureComponent 其实是在内部帮我们简单实现了一下shouldComponentUpdate的功能,以便提供组件的性能;这里的简单指是:对prop和state做浅比较,若浅比较结果相同,则该组件以及其子组件不做render;否则,render。

使用PureComponent注意事项:
	PureComponent主要针对prop和state为基本数据类型,如bool、string、number;
	对于数组和对象等引用类型,则要引用不同,才会渲染;如果引用相同,则PureComponent浅比较返回结果相同,不做render;
	PureComponent 中不建议再另外重写shouldComponentUpdate方法,否则会报warning信息:
	PureComponent的最好作为展示组件,如果prop和state每次都会变,PureComponent做浅比较也会影响性能,可以考虑直接用Component;
	对于prop和state数据结构比较复杂的情况,可以考虑自己重写shouldComponentUpdate方法来做优化;
6、react中的ref的3种方式
方式1: string类型绑定
类似于vue中的ref绑定方式,可以通过this.refs.绑定的ref的名字获取到节点dom
注意的是 这种方式已经不被最新版的react推荐使用,有可能会在未来版本中遗弃
 
方式2: react.CreateRef()
通过在class中使用React.createRef()方法创建一些变量,可以将这些变量绑定到标签的ref中
那么该变量的current则指向绑定的标签dom
 
方式3: 函数形式
在class中声明函数,在函数中绑定ref
使用这种方法可以将子组件暴露给父组件以使得父组件能够调用子组件的方法
通过函数的方法绑定ref可以将整个子组件暴露给父组件

当在子组件中调用onRef函数时,正在调用从父组件传递的函数。this.props.onRef(this)这里的参数指向子组件本身,父组件接收该引用作为第一个参数:onRef = {ref =>(this.child = ref)}然后它使用this.child保存引用。之后,可以在父组件内访问整个子组件实例,并且可以调用子组件函数。
6、组件按需加载
(实现方式,需要的依赖)懒加载

1、vue异步组件技术
	vue-router配置路由,使用vue的异步组件技术,可以实现按需加载。
	但是,这种情况下一个组件生成一个js文件。

2.import()

3.webpack提供的require.ensure()

4.第三方库比如react-loadable   

5.lazyload-loader

7、从url输入到返回请求的过程

  • 先会进行 url 解析(也就是编码),根据 dns (domain name system)域名解析系统进行 ip 查找。
    1、浏览器会检查缓存中有没有这个域名对应的解析过的IP地址,如果缓存中有,这个解析过程就将结束
    2、操作系统会检查hosts文件是否有记录,有的话就会把相对应映射的IP返回 (域名劫持,黑客篡改hosts文件)
    3、如果至此还没有命中域名,就去请求本地域名服务器(LDNS)来解析这个域名,这台服务器一般在你的城市的某个角落,距离你不会很远
    4、如果LDNS仍然没有命中,就直接跳到根域名服务器(全球13台,固定ip地址)请求解析。
    (1)根域名服务器返回给LDNS一个所查询域的主域名服务器(gTLD Server,国际顶尖域名服务器,如.com .cn .org等)地址。
    (2)此时LDNS再给上一步返回的主域名服务器发送请求。
    (3)主域名服务器查找并返回这个域名对应的Name Server的地址,这个Name Server就是网站注册的域名服务器。
    (4)最后域名服务器根据映射关系表找到目标ip,返回给LDNS。LDNS缓存这个域名和对应的ip
    (5)LDNS把解析的结果返回给用户,用户根据TTL值缓存到本地系统缓存中。
    总结:简单来说,一条域名的DNS记录会在本地有两种缓存:浏览器缓存和操作系统(OS)缓存。在浏览器中访问的时候,会优先访问浏览器缓存,如果未命中则访问OS缓存,最后再访问DNS服务器(一般是ISP提供),然后DNS服务器会递归式的查找域名记录,然后返回。
    问题:为什么要进行url的解析?
    是因为URL中有些字符会引起歧义,如:name1=‘va&lu=’,URL编码只是简单的在特殊字符的各个字节(16进制)前加上“%”即可。例如,我们对上述会产生歧义的字符进行编码后的结果:name1=va%26lu%3D,这样服务器会把紧跟在”%”后的字节当成普通的字节,不会把它当成各个参数或键值对的分隔符。
    例如,URL参数字符串中如果包含”&”或者”%”势必会造成服务器解析错误,所以需要对其进行编码。
    又如,URL的编码格式采用的是ASCII码而不是Unicode,这也就是说你不能在URL中包含任何非ASCII字符,比如中文。否则如果客户端浏览器和服务器端浏览器支持的字符集不同的情况下,中文可能会造成问题。

    前端的dns优化,可以在html页面头部写入dns缓存地址,比如(Chrome和Firefox 3.5本身对DNS预解析做了相应优化设置)
    用meta信息来告知浏览器, 当前页面要做DNS预解析:
    在页面header中使用link标签来强制对DNS预解析:

  • TCP三次握手建立链接
    1、第一次握手:客户端发送syn包(seq=x)到服务器,并进入SYN_SEND状态,等待服务器确认;
    2、第二次握手:服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(seq=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;
    3、第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态
    问题:为啥不是两次握手?
    假如client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,延误到连接释放以后的某个时间才到达server。
    本来这是一个早已失效的报文段,但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据,但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。
    简单来说就是 因为第二次握手后,主机B还不能确认主机A已经收到确认请求,也是说B认为建立好连接,开始发数据了,结果发出去的包A一直都没收到

  • 发送请求

  • 服务器返回请求的文件(html)

  • 浏览器渲染

    • HTML parser -> DOM Tree
      • 标记化算法,进行元素状态标记
      • dom树构建
    • CSS parser --> Style Tree
      • 解析css代码,生成样式树
    • attachment --> Render Tree
      • 结合dom树与style树,生成渲染树
    • layout:布局 根据渲染树将节点树的每一个节点布局在屏幕上的正确位置
    • GPU painting:像素绘制页面
      页面渲染优化:
      HTML文档结构层次尽量少,最好不深于六层;
      脚本尽量后放,放在前即可;
      少量首屏样式内联放在标签内;
      样式结构层次尽量简单;
      在脚本中尽量减少DOM操作,尽量缓存访问DOM的样式信息,避免过度触发回流;
      减少通过JavaScript代码修改元素样式,尽量使用修改class名方式操作样式或动画;
      动画尽量使用在绝对定位或固定定位的元素上;
      隐藏在屏幕外,或在页面滚动时,尽量停止动画;
      尽量缓存DOM查找,查找器尽量简洁;
      涉及多域名的网站,可以开启域名预解析

7、什么是Time Slicing

React 在渲染(render)的时候,不会阻塞现在的线程
react fiber

7、react16.X生命周期的改变

新增 static getDerivedStateFromProps(props,state)
该函数必须有返回值。当props传入的内容不需要影响state,就必须返回一个null,否则返回一个对象来改变state ,静态方法不能调用this

getSnapshotBeforeUpdate(prevProps, prevState)
getSnapshotBeforeUpdate会在最终的 render 之前被调用,也就是说在getSnapshotBeforeUpdate中读取到的 DOM 元素状态是可以保证与componentDidUpdate中一致的,返回值会传入到componenDtidupdate中

三、网络

1、http/https协议

http1.0协议缺陷:

  1. 无法复用链接,完成及断开,重新启动慢和TCP3次捂手
  2. heade of line blocking:线头阻塞,导致请求之间相互影响
  3. 使用的是文本传输
  4. 请求和响应报文header信息冗余量大
  5. 只能由客户端发起单向请求

1.1改进

  1. 长连接(默认keep-alive),复用
  2. pipelining管道,在这个管道上浏览器可同时发送多个请求,但是服务器的响应只能一个接着一个的返回
  3. host字段指定对应的虚拟站点
  4. 新增功能
    • 断点续传
    • 身份认证
    • 状态管理
    • cache缓存
      • cache-control
      • expires
      • last-modified
      • etag

http2.0

  1. 二进制分帧层
    在应用层与传输层之间增加一个二进制分帧层,二进制传输单位是帧和流,帧组成了带有ID标识的流
  2. 多路复用
    同域名下所有的通信都在同一个TCP链接上完成,单个连接上可以并行交错的请求和响应,之间互不干扰,数据流以消息的形式发送,而消息由一个或多个帧组成,多个帧之间可以乱序发送,因为可以根据帧首部的流标示ID重新组装。消除了因多个 TCP 连接而带来的延时和内存消耗
  3. 请求优先级
    既然所有的资源都是并行发送的,那么就需要优先级的概念了,对于重要的文件优先传输,加速页面渲染
  4. 首部压缩
    使用专门的HPACK算法。维护一个首部表,对于相同的头部,不必要再通过请求发送
  5. 服务端推送
    服务端可主动推送其他资源,不用等到浏览器解析到相应位置时再发起请求
http2.0改进对优化的影响
  1. 因为“所有的HTTP2.0的请求都在一个TCP链接上”,“资源合并减少请求”,比如CSS Sprites,多个JS文件、CSS文件合并等手段没有效果,或者说没有必要。
  2. 因为“多路复用”,采用“cdn1.cn,cdn2.cn,cdn3.cn,打开多个TCP会话,突破浏览器对同一域名的链接数的限制”的手段是没有必要的。因为因为资源都是并行交错发送,且没有限制,不需要额外的多域名并行下载。
  3. 因为“服务器推送”,内嵌资源的优化手段也变得没有意义了。而且使用服务器推送的资源的方式更加高效,因为客户端还可以缓存起来,甚至可以由不同的页面共享(依旧遵循同源策略)。

12、http 缓存


定义:http 缓存是指当客户端向服务器发送请求时,会先抵达浏览器缓存,如果浏览器缓存中有请求资源的副本,则直接使用浏览器缓存
​ 分类:有强缓存和协商缓存
​ 强缓存:对于强缓存,服务器会通知浏览器一个缓存时间,在缓存时间范围内,下次请求,直接使用缓存;如果不在时间范围内,就执行协商缓存
​ 协商缓存:将缓存信息中的 Etag 和 last-Modified 通过请求发送给服务器;由服务器校验,返回 304 状态码时,直接使用缓存;如果服务器数据有跟新,则返回 200 状态码;并将更新的数据和请求一起发送回来

什么是session?

服务器为了保存用户状态而创建的一个特殊的对象。当浏览器第一次访问服务器时,服务器创建一个session对象(该对象有一个唯一的id,一般称之为sessionId),服务器会将sessionId
以cookie的方式发送给浏览器。

当浏览器再次访问服务器时,会将sessionId发送过来,服务器依据sessionId就可以找到对应的session对象。

cookie与domain

domain是cookie的一个属性,表示改cookie属于哪个域名下,哪些域名允许被访问,同域下的单点登录就是这个原理

Cookie是不可以跨域名的,隐私安全机制禁止网站非法获取其他网站的Cookie。正常情况下,同一个一级域名下的两个二级域名也不能交互使用Cookie,比如test1.mcrwayfun.com和test2.mcrwayfun.com,因为二者的域名不完全相同。如果想要mcrwayfun.com名下的二级域名都可以使用该Cookie,需要设置Cookie的domain参数为.mcrwayfun.com,这样使用test1.mcrwayfun.com和test2.mcrwayfun.com就能访问同一个cookie。
注意:只能设置顶域和自己的域,不能设置其他的域

27、HTTP的状态码


200 OK 请求成功。一般用于 GET 与 POST 请求
3 开头 重定向
300 多种选择。请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表用于用户终端(例如:浏览器)选择
301 永久移动。请求的资源已被永久的移动到新 URI,返回信息会包括新的 URI,浏览器会自动定向到新 URI。今后任何新的请求都应使用新的 URI 代替
302 临时移动。与 301 类似。但资源只是临时被移动。客户端应继续使用原有 URI
303 查看其它地址。与 301 类似。使用 GET 和 POST 请求查看
304 未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源
305 使用代理。所请求的资源必须通过代理访问
306 已经被废弃的 HTTP 状态码
307 临时重定向。与 302 类似。使用 GET 请求重定向
400 客户端请求的语法错误,服务器无法理解
401 请求要求用户的身份认证,对于需要登录的网页,服务器可能返回此响应。
402 保留,将来使用
403 服务器理解请求客户端的请求,但是拒绝执行此请求。拒绝或者禁止访问。
404 服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面
405 客户端请求中的方法被禁止
406 N 服务器无法根据客户端请求的内容特性完成请求
407 请求要求代理的身份认证,与 401 类似,但请求者应当使用代理进行授权
408 服务器等待客户端发送的请求时间过长,超时
409 服务器完成客户端的 PUT 请求时可能返回此代码,服务器处理请求时发生了冲突
410 客户端请求的资源已经不存在。410 不同于 404,如果资源以前有现在被永久删除了可使用 410 代码,网站设计人员可通过 301 代码指定资源的新位置
411 服务器无法处理客户端发送的不带 Content-Length 的请求信息
412 客户端请求信息的先决条件错误
413 由于请求的实体过大,服务器无法处理,因此拒绝请求。为防止客户端的连续请求,服务器可能会关闭连接。如果只是服务器暂时无法处理,则会包含一个 Retry-After 的响应信息
414 请求的 URI 过长(URI 通常为网址),服务器无法处理
415 服务器无法处理请求附带的媒体格式
416 客户端请求的范围无效
417 服务器无法满足 Expect 的请求头信息
500 服务器内部错误,无法完成请求
501 服务器不支持请求的功能,无法完成请求
502 作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应
503 由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的 Retry-After 头信息中
504 充当网关或代理的服务器,未及时从远端服务器获取请求
505 服务器不支持请求的 HTTP 协议的版本,无法完成处理

5、状态码:301 跟 302 的区别

301 是永久移动。请求的资源已被永久的移动到新 URI,返回信息会包括新的 URI,浏览器会自动定向到新 URI。今后任何新的请求都应使用新的 URI 代替
302 是临时移动,与 301 类似。但资源只是临时被移动。客户端应继续使用原有 URI

3、http 和 https


http 概述:超文本传输协议,是互联网上应用最为广泛的一种网络协议

http 的缺点 1.通信使用明文可能会被窃听。 2.不验证通信方的身份可能遭遇伪装。 3.无法证明报文的完整性,可能已遭篡改。

https 就是在安全的传输层上发送的 http。它在将 http 报文发送给 TCP 之前,先将其发送给了一个安全层 ,对其进行加密。http 安全层是通过 ssl 及其现代替代协议 TSL 来实现的。

https 的优点
(1)使用 HTTPS 协议可认证用户和服务器,确保数据发送到正确的客户机和服务器;
(2)HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,要比 http 协议安全,可防止数据在传输过程中不被窃取、改变,确保数据的完整性。

https 的缺点
但是 https 因为加了层 ssl,所以在效率方面比较低,会使页面加载的时长延长近 50%,也会增加 10-20%的耗电。
需要安装证书,在一定基础上增加部署费用,并且报文加密解密对数据传递有一点的效率影响。

4、WebSocket 是否有了解, 和普通接口 http 有什么区别


WebSocket protocol 是 HTML5 一种新的协议。它实现了浏览器与服务器全双工通信(full-duplex)。一开始的握 手需要借助 HTTP 请求完成。

​ HTTP 请求缺点:会导致过多不必要的请求,浪费流量和服务器资源,每一次请求、应答,都浪费了一定流量在 相同的头部信息上

​ 然而 WebSocket 的出现可以弥补这一缺点。在 WebSocket 中,只需要服务器和浏览器通过 HTTP 协议进行一个握 手的动作,然后单独建立一条 TCP 的通信通道进行数据的传送。

​ **webSocket 原理:(webSocket)**

​ WebSocket 同 HTTP 一样也是应用层的协议,但是它是一种双向通信协议,是建立在 TCP 之上的。

1. 浏览器、服务器建立 TCP 连接,三次握手。这是通信的基础,传输控制层,若失败后续都不执行。
2. TCP 连接成功后,浏览器通过 HTTP 协议向服务器传送 WebSocket 支持的版本号等信息。(开始前的 HTTP 握手)
3. 服务器收到客户端的握手请求后,同样采用 HTTP 协议回馈数据。
4. 当收到了连接成功的消息后,通过 TCP 通道进行传输通信。
   WebSocket 与 HTTP 的关系

​ **相同点:**

1. 都是一样基于 TCP 的,都是可靠性传输协议。

   2. 都是应用层协议

   不同点:

   3. WebSocket 是双向通信协议,模拟 Socket 协议,可以双向发送或接受信息。HTTP 是单向的。
   4. WebSocket 是需要握手进行建立连接的。

为什么要有 Etag

HTTP1.1Etag 的出现主要是为了解决几个 Last-Modified 比较难解决的问题:

  • 一些文件也许会周期性的更改,但是内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新 GET;
  • 某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说 1s 内修改了 N 次),If-Modified-Since 能检查到的粒度是秒级的,使用 Etag 就能够保证这种需求下客户端在 1 秒内能刷新 N 次 cache。
  • 某些服务器不能精确的得到文件的最后修改时间。

四、性能优化

12.浏览器优化

减少请求数量

一.图片处理

1、雪碧图 - gulp Base64 使用字体图标来代替图片 - 自定义字体 @font-face{} 在安卓下可以使用 webp 格式的图片

二.减小资源大小 - grunt gulp webpack

1、HTML 压缩 2、CSS 压缩 3、JS 压缩与混乱 4、图片压缩

三.优化网络连接

CDN 即内容分发网络,它能够实时地根据网络流量和各节点的连接、负载状

用户可就近取得所需内容,解决 Internet 网络拥挤的状况,提高用户访问网站的响应速度

四.优化资源加载

资源加载位置

1、CSS 文件放在 head 中,先外链,后本页

2、JS 文件放在 body 底部,先外链,后本页

3、body 中间尽量不写 style 标签和 script 标签

资源加载时机

1、异步 script 标签

2、模块按需加载需要根据路由来加载当前页面需要的业务模块

3、资源懒加载与资源预加载

五.减少重绘回流

当 render tree 中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建。这就称为回流(reflow)。

当 render tree 中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局的,比如 background-color。则就叫称为重绘。

回流必将引起重绘,而重绘不一定会引起回流。

优化

减少回流和重绘

css3 硬件加速(GPU 加速)

六.【DOM 优化】

1、缓存 DOM2、减少 DOM 深度及 DOM 数量 3、批量操作 DOM4、批量操作 CSS 样式 5、在内存中操作 DOM6、DOM 元素离线更新 7、DOM 读写分离 8、事件代理 9、防抖和节流 10、及时清理环境

安全

XSS攻击:注入恶意代码

xss攻击(Cross Site Scripting)跨站脚本攻击,恶意攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户的目的

对用户过于信任

  • cookie设置httpOnly
    如果HTTP响应头中包含HttpOnly标志,只要浏览器支持HttpOnly标志,客户端脚本就无法访问cookie
  • 转移页面上输入的内容和输出的内容

CSRF:跨站请求伪造,防护

通过获取cookie伪装成自己发送一些非本意的请求

防御策略:

  1. 验证请求头中的 referer字段,判断请求的来源地址。
    Referer 的值是由浏览器提供的,虽然 HTTP 协议上有明确的要求,但是每个浏览器对于 Referer 的具体实现可能有差别,并不能保证浏览器自身没有安全漏洞。使用验证 Referer 值的方法,就是把安全性都依赖于第三方(即浏览器)来保障,从理论上来讲,这样并不安全,IE6 的referer有可能会被篡改
  2. 在请求地址中加入token
    在请求中放入黑客所不能伪造的信息,并且该信息不存在于 cookie 之中,随机产生的 token,服务器验证token
  3. 请求头中加入token自定义属性
    基于XMLHttpRequest可以将token以自定义属性的形式放在请求头中,不会被记录到浏览器的地址栏,不用担心token会通过referer泄漏出去,但是只能使用XLMHttpRequest请求
  • get不修改数据
  • 不被第三方网站访问到用户的cookie
  • 设置白名单,不被第三方网站请求
  • 请求校验

五、react

什么是合成事件

1 React合成事件特点

React自己实现了一套高效的事件注册,存储,分发和重用逻辑,在DOM事件体系基础上做了很大改进,减少了内存消耗,简化了事件逻辑,并最大化的解决了IE等浏览器的不兼容问题。与DOM事件体系相比,它有如下特点

  1. React组件上声明的事件最终绑定到了document这个DOM节点上(17之后改为委托在挂载的容器上),而不是React组件对应的DOM节点。故只有document这个节点上面才绑定了DOM原生事件,其他节点没有绑定事件。这样简化了DOM原生事件,减少了内存开销
  2. React以队列的方式,从触发事件的组件向父组件回溯,调用它们在JSX中声明的callback。也就是React自身实现了一套事件冒泡机制。我们没办法用event.stopPropagation()来停止事件传播,应该使用event.preventDefault()
  3. React有一套自己的合成事件SyntheticEvent,不同类型的事件会构造不同的SyntheticEvent
  4. React使用对象池来管理合成事件对象的创建和销毁,这样减少了垃圾的生成和新对象内存的分配,大大提高了性能
    合成事件是根据不同类型绑定到document上,触发函数统一是dispatchEvent
  5. 减少内存消耗,提升性能,不需要注册那么多的事件了,一种事件类型只在 document 上注册一次

统一规范,解决 ie 事件兼容问题,简化事件逻辑
原生事件对象封装,对原生事件升级改造,浏览器事件的兼容

onclick方法中的e其实是对原生事件对象进行包装后的、原生对象被放在了e.nativeEvent中

react会根据当前的事件类型来使用不同的合成事件对象,比如鼠标单机事件 - SyntheticMouseEvent,焦点事件-SyntheticFocusEvent等,但是都是继承自SyntheticEvent。
对原生事件升级改造 例如input上绑定onchange方法 我们向文本框输入内容的时候,是可以实时的得到内容的。
然而原生只注册一个onchange的话,需要在失去焦点的时候才能触发这个事件,所以这个原生事件的缺陷react也帮我们弥补了

事件注册 - 组件挂载阶段,根据组件内的声明的事件类型-onclick,onchange 等,给 document 上添加事件 -addEventListener,并指定统一的事件处理程序 dispatchEvent。
事件存储 - 就是把 react 组件内的所有事件统一的存放到一个对象里,缓存起来,为了在触发事件的时候可以查找到对应的方法去执行。
把所有的事件和事件类型以及react 组件进行关联,把这个关系保存在了一个对象(listenerBank)里,然后在事件触发的时候去根据当前的 组件id和 事件类型查找到对应的 事件fn

六、git相关

git cherry-pick是做什么用的?

可以将另一个分支上的某个commit合并到当前分支上

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值