面试总结2

137 阅读26分钟

目录


react、vue、angular、jq:生命周期,特点,优缺点,版本区别

主题reactvueangularjq
体系结构只有mvc中的view mvcmvvm完成的mvc
渲染可以进行服务端渲染客户端渲染
dom使用虚拟dom使用虚拟dom使用真实dom
数据绑定单向数据流双向数据绑定双向数据绑定
调试编译时调试运行时调试
作者facebook尤雨溪google
定义facebook在2011年开发的js库,2015年开源,遵循基于组件的方法,有助于构建可重用的组件
特点使用虚拟dom,可以进行服务端渲染,单向数据流Vue.js在模板中提供了指令,过滤器等,可以非常方便,快捷地操作Virtual DOM。
优点方便在客户端和服务端使用,因jsx,代码可读性高,由于虚拟dom,提高性能简单易学、双向数据绑定、运行速度快虚拟dom,单页面应用
缺点只是一个庞大的库,不是一个完整框架,需要时间来理解vue不支持IE8
生命周期- componentWillMount渲染前,客户端服务端都执行
  • componentDidMount第一次渲染后在客户端执行
  • componentWillReceiveProps当从父类接受到props
  • shouldComponentUpdate根据条件返回true/false
  • componentWillUpdate在DOM中进行渲染之前调用
  • componentDidUpdate渲染发生后立即调用
  • componentWillUnmount从DOM卸载组件后调用,清理内存空间 | - beforeCreate(创建前) 在数据观测和初始化事件还未开始
  • created(创建后) 完成数据观测,属性和方法的运算,初始化事件,$el属性还没有显示出来
  • beforeMount(载入前) 在挂载开始之前被调用,相关的render函数首次被调用。实例已完成以下的配置:编译模板,把data里面的数据和模板生成html。注意此时还没有挂载html到页面上。
  • mounted(载入后) 在el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用。实例已完成以下的配置:用上面编译好的html内容替换el属性指向的DOM对象。完成模板中的html渲染到html页面中。此过程中进行ajax交互。
  • beforeUpdate(更新前) 在数据更新之前调用,发生在虚拟DOM重新渲染和打补丁之前。可以在该钩子中进一步地更改状态,不会触发附加的重渲染过程。
  • updated(更新后) 在由于数据更改导致的虚拟DOM重新渲染和打补丁之后调用。调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务器端渲染期间不被调用。
  • beforeDestroy(销毁前) 在实例销毁之前调用。实例仍然完全可用。
  • destroyed(销毁后) 在实例销毁之后调用。调用后,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务器端渲染期间不被调用。

Mvc、mvvm、flux、redux、vuex定义与特性

mvcmvvmfluxreduxreact-reduxvuex
模式model 数据层view 视图层control 逻辑层当用户对view层有改变时,它负责修改响应的model,model发生变化,负责去更新视图层model:数据层view: 视图层vm:view和model通过vm层自动同步强制的单向数据流的架构模式,洋葱圈模式:用户通过点击等等一些事件,触发一个action,通过store.dispatch分发这个action,通过Reducer这个存函数去改变store中的状态,通过监听事件subscribe监听store的变化,然后才会视图层更新import引入storegetState获取状态dispatch修改状态subscribe监听跟新
组件- action:描述发生事情的对象
  • reducer:纯函数,确定状态如何改变,返回新的状态
  • store:整个状态存储的地方
  • view:只显示store提供的数据 | Provider:将store放进this.context 里,为connect提供获取store的途径;Connect:将getState、dispatch合并进this.props,自动监测更新,接受mapStateToProps、mapDispatchToProps两个方法,返回一个高阶函数,高阶函数接受一个组件,返回一个高阶组件(其实就是给传入的组件增加一些属性和功能),connect根据传入的,将state和dispatch(action)挂在子组件的props上, | | | 原则 | | | | - 单一来源store存储所有状态
  • 状态只读,改变状态需要触发动作,动作是描述变化的js对象
  • 使用纯函数进行更改
  • 数据流:
  • 中间件:增强对dispatch功能        redux-logger:提供日志输出        redux-thunk: 处理异步操作,对actionCreator进行操作        redux-promise:处理异步操作        redux-saga: 把异步请求放在了saga文件中 | | | | 优点 | | | | 结果可预测性:只有一个store的状态来源可维护性更高服务端渲染 | | | | 缺点 | - 对DOM操作的代价非常高
  • 程序运行缓慢,效率低下
  • 内存浪费严重
  • 由于循环依赖性,组件模型需要围绕models和iviews进行创建 | | | 一个组件所需要的数据,必须由父组件传递过来,不能直接从store中取 | | |

列表key属性、jsx原理

key:识别唯一的虚拟dom元素及其驱动ui的标识,必须是唯一的数字或字符串,他们通过回收DOM中当前所有的元素来帮助react优化渲染,react只是重排元素,而不是重新渲染,提高性能

jsx: react使用的一种文件,利用js和类似html的模板语法,让html文件更容易理解,提高性能;

         浏览器只能处理js对象,不能读取js中的jsx,需要用babel JSX转换器将jsx转为js对象,传给浏览器       


React如何减少组件无重用渲染

问题答案解决
state的值未变化,是否会重渲染shouldComponentUpdate(nextProps, nextState)nextState.num ===this.state.num  return false, 只能是偏平的对象,如果nextState.numObj.num === this.state.numObj.num  二者都指向堆中同一个对象,所以一直都是true,shoucomponentUpdate就失效了如果获取到不同的numObj?1、ES6的object assign();2、利用JSON.parse(JSON.strigify(data))深拷贝
组件state和父组件传的props都没变,是否会重渲染可能

React Hooks相关问题

hooks优势:

        在无需修改组件结构的情况下复用状态

        将组件中想关联的部分成更小的函数

函数组件的渲染过程:每一次渲染,就是函数的重新执行

useState和setState的区别:

        useState 只能在函数组件;在函数组件中可以声明多个;修改state时,同一个useState声明的值被覆盖,多个useState声明的值被触发多次渲染;设置相同值,不会重渲染;

        setState  只能在类组件; 在类组件中必须声明在this的state对象中;修改sate时,多次setState的对象呗合并处理;设置相同值会被重渲染;

useState和useReducer的初始值如果是个执行函数返回值,执行函数是否会多次执行:

   前者不会,后者会

        useState设置初始值时,如果初始值是个值,可以直接设置,如果是个函数返回值,建议使用回调函数设置(只会在初始化时执行一次);

        useReducer设置初始值时,只能是个值,不能是回调函数,因为组件重新渲染时,会重新执行函数

useEffect如何模拟componentDidMount、componentUpdate、componentWillUnMount生命周期

        componentDidMount:    useEffect(() => {}, [])

        componentUpdate:        useEffect(() => { if (count !== 0) { } }, [count])   使用条件判断依赖项是否为初始值

        componentWilllunMount: useEffect(() => {  return () => {} }, [])   返回函数被执行,组件被卸载, 依赖项必须为空数组,如果不是,是在组件重新渲染,清理上一次数据时触发

如何在useEffect中正确的为DOM设置事件监听

        在useEffect中设置监听,在return的函数中清理,取消监听事件

useEffect、useCallback、useMemo中取到的state、props为什么会是旧值

       三者都具有缓存功能,如果依赖项为空数组,那么改变多少次,变量都是初始值

useEffect为何会无限执行

如果没有设置依赖项,并且在useEffect中更新state,会导致无限重复渲染   useEffect(() => { setCount(count + 1) })

       如何解决无限重渲染: 设置空数组依赖项,相当于给页面初始值设置了一个新值

       依赖项设置[count, page],count+1, page+1, 也导致的页面重复渲染:useEffect(() => { setPage(page => page + 1) }, [count])

竞态:多次刷新页面,有时展示0,有时展示10

        设置布尔值变量进行追踪,  useEffect(() => { 

          let didCancel = false;

         const getData = async () => { const result = await fetchData(id)  if (didCancel) { setData(result) }}

         getData()

         return () => {  didCancel = true  }

        , [id])

如何在函数组件中保存住非state/props的值,函数组件实例的属性

      重新渲染时,countRef不会被重新赋值,但modal构造函数会多次执行

      

如何保证在函数组件的每一帧里访问到的state值是相同的

        函数组件是没有this指向的,为了保存组件实例的属性,用useRef操作,将普通类型的值转为一个带有current属性的对象引用,来保证每次访问到的属性值是最新的

如何在函数组件中保存一些属性,跟随组件进行创建和销毁

当useCallback会频繁触发时,如何优化

        使用useReducer替代useState,useReducer返回的dispatch函数自带memoize,不会再多次渲染时改变,因此useCallback中不需要将dispatch作为依赖项

        

     向setState中传递函数,在setCount中使用函数作为参数时,接受到的值是最新的state值

useCallback和useMemo的使用场景有何区别    

      useMemo返回时一个值,可以是属性,可以是函数(包括组件),用来缓存计算量比较大的函数结果,避免不必要的重复计算

      useCallback的返回值只能是函数

useMemo和React.memo不同

      useMemo是对组件内部的一些数据进行优化和缓存

      React.memo是对函数组件进行包裹,对组件内部的state、props进行浅比较,判断是否需要进行渲染

useContext使用

定义静态属性的方式

      function component

      

Sass(scss)、less、css: 区别,特点

less是基于js的,在客户端处理,2009年开源;变量用@

sass是基于ruby的,在服务端处理,2007年开源;变量用$

scss语法用{}取代了sass中的缩进

sass与less相同处:1、运算,css用上数学;3、作用域,全局/局部修改样式;4、嵌套

多行注释会被编译出来,单行不会


Es6、es7、es8、H5、css3:特性,map, set,

ES6(2015)ES7(2016)ES8(2017)ES9(2018)ES10(2019)H5Css3
类:子类必须在construcor中指定super函数,否则会报错如果没有指定construtor,默认带super函数的constructor将会被添加Array.includes() => true/falseasync/await异步迭代array的flat(reduce归纳,降维)与flatMap(concat合并)的操作[1,2,[3,4]].flat() => [1,2,3,4] 降一维,去除数组空项[1,2,[3,4,[5,6]]].flat(Infinity) 任意深度的展开嵌套数组[1,2,3,4].map(x => [x2]) => [[2], [4],[6],[]][1,2,3,4].flatMap(x => [x2]) => [2,4,6,8]只压平一层语义化标签HeaderNavSectinArticlefooter圆角  border-radius多背景 background过滤旋转 scale缩放 移动 tansform倾斜
模块化:主要由export和import组成;import引入其他模块,export规定对外暴露的名字,都有自己单独的作用域Object.values()Promise.finally()无论promise成功失败都运行代码string的strimStart()和strimEnd去除收尾空白符表单元素passwordemailurladdressdate
箭头函数:解决this指向,Object.entries() 返回键值对的数组rest/spread属性多媒体audiovedio
模板字符串string paddingpadStart()padEnd()缓存浏览器缓存:localstorage, sessionStorage
数组的解构赋值新的通信方式: websoket
延展操作符:...[]/{}3d图像: canvas svg webgl
promise对象
let/const 块级作用域,没有变量声明提升,否则会报错,不能重复定义,报错let定义,可以改,const定义,如果是引用类型,可以修改对象里的属性值(因为对象指针没变),否则会报错

Js基本数据类型

基本类型:number、string、boolean、undefined、null   值存在栈中

引用类型:object、array、function   引用存在栈中,真实的数据在堆中,不同的引用可以指向堆中的同一个对象

判断引用类型方法:Object.prototype.toString.call(target) === 'Array' / 'Object'

深拷贝:重新创造一个新对象,新旧对象互不影响

深拷贝方法:

       JSON.parse(JSON.stringify())  但不能深拷贝函数,fn 深拷贝是个null,因为JSON.stringify()是将一个js对象或数组转成json字符串,不能接受函数;

        _.clonDeep

浅拷贝:赋值的是对象的引用,同一个对象,影响;

浅拷贝方法:

        Object.assign()对象有一层,是深拷贝,否则是浅拷贝;

         Array.concat() ;

         Array.slice();


flex布局、垂直居中、清除浮动、BFC、三栏布局、两栏布局、动画、盒模型、等宽等高

BFC:块级格式化上下文,一个独立的渲染区域,内部如何布局,不会影响外部

特点:内部元素会在垂直方向上一个接一个放;

           垂直方向上的距离由margin决定;

           bfc区域不会与float的元素区域重叠;

形成BFC:浮动元素,float除none以外的值;

                绝对定位的元素,position: absolute,fixed;

                display: inline-block,table-cell,flex;

                overflow除visible以外的值:hidden,auto,scroll;

                body根元素;

盒模型:

           标准盒模型(W3C盒模型): content + padding + border + margin         width和height不包含padding和border

            box-sizing: content-box(浏览器默认设置)  j将采用标准盒模型

           怪异盒模型(IE盒模型):width(content + padding + border) + margin    width和heigh都包含padding和border

           box-sizing: border-box;  将采用怪异盒模型

           box-sizing: inherit; 从父元素继承box-sizing属性的值

垂直居中让图片垂直局居中不固定宽高垂直居中清除浮动三栏布局(左右固定高度,中间自适应)两栏布局给定宽度,如何设置高与宽度相等图片大小不一致,如何垂直水平居中
父:display: table;子:display: table-cell;       vertical-align:middle;优点:content动态改变高度,当父没有足够空间,content不会被截断缺点:IE中不好使父:line-height: height;       text-align: center;父: display: table-cell;        text-align: center;        vertical-align: middle;父:float: left;子:clear: both;       height: 200px;左栏左浮动,右栏右浮动,设置宽度高度;中间设置margin撑开距离,且中间不设置宽度,高度自适应;html布局时,中间栏放在左右两栏的后面,否则,右栏会在中间栏的右下角显示左栏浮动,右边margin-left撑开width: 33%;padding: 14% 0;padding上下设置,左右为0上下加中间文字=width图片父容器:                       width: xx;                       height: xx;                       float: left;                       text-align: center;图片: vertical-align: middle;与图片同级添加空:         display: inline-block;         width: 0;         height: 100%;         overflow: hidden;         vertical-align: middle;
父:position: relative;子:position: absolute;       top: 50%;       margin-top: -1/2height;       left: 50%;       margin-left: -1/2width;优点:使用所有浏览器;缺点:没有足够空间,content会消失同左父: display: flex;子: margin: auto;父:overflow: auto;优点: 浏览器支持好;缺点: 内部宽高超过父时,出现滚动条父:overflow: hidden;缺点:不能喝position配合使用左栏定位再左侧,右栏定位再右侧,中间栏不舍宽度,靠margin撑开父:display: flex左栏宽度固定,右栏flex:1
父:position: relative;子:position: absolute;       left: 0; top: 0; bottom: 0; right: 0;       height: xx;       width: xx;       margin: auto;优点:简单缺点:IE中无效;          没有足够空间,content被截断同左同左父定义伪类div:after {     content: "";     clear: both;}.clearfix {     zoom: 1;   兼容IE}三栏左浮动,左栏margin-left: -100%; 右栏margin-left: 负右栏高度;中间栏宽度100%,布局中间栏放在第一个父:position:relative左边:position: absolute;       left: 0;       top: 0;右边:margin-left撑开距离
父:display: flex;       aligin-items: center;  垂直居中       justify-content: center; 水平居中或者父:display:flex;       justify-content: center; 水平居中子:align-self: center同左同左父:height: xx;缺点:需要设置固定高度
父: positino: relative;子: position:absolute;        top: 50%;        left: 50%;       transform: translate(-50%, -50%)同左同左

移动端适配

         设备像素比dpr = 物理像素 / 设备独立像素(逻辑像素)

         vw 时相对屏幕的相对单位,100vw = ideal viewport 宽, 100vh = ideal viewport 高

         1px边框问题及解决方案:

         1px的css逻辑像素不等于1px的物理像素,所以实际显示出来的要粗

          用box-shadow模拟边框来实现1px border

           .boder{ border: none; height: 100px; width: 100%; box-shadow: 0 1px 1px -1px rgba(0,0,0,0.5) }

解决方法 实现优点缺点
媒体查询meida通过查询设备宽度来执行不同的css代码   @meida screen and (max-width: 600px) {}图片便于修改,只需要修改css跳转屏幕宽度的似乎还不用刷新页面即可响应式展示代码量比较大,维护不方便为了兼顾大屏幕或高清设备,会造成其他设备资源浪费,特别是加载图片资源为了兼顾移动端和pc端各自响应式展示效果,难免会损失各自持有的交互方式
flex弹性布局viewport固定 <meta name="viewport" content="width=device-width,initial-scale=1,maxinum-scale=1,user-scalable=no"高度定死,宽度自适应,元素采用px单位initial-scale:页面初始缩放值,可带小数;minimum-scale:设置页面的最小缩放值,可带小数maximum-scale:设置页面的最大缩放值,可带小数user-scalable:页面是否允许缩放,no不允许,yes允许;no时 ios>=10的safari有兼容性问题
rem+viewport缩放根据屏幕宽度设置rem值,需要适配的元素都使用rem做单位,不需要适配的采用px(1em=16px)rem是一个相对root的单位,
rem方式

跨域、解决方法

        跨域:协议、域名、端口号不同

        正向代理代理客户端,为客户端收发请求,隐藏客户端(翻墙,a想访问google,但它访问不了,但b可以,所以a先访问b, b再访问google,数据返回后,转发给a)

        反向代理代理服务端,为服务端收发请求,隐藏服务端

       好处:

       反向代理保护原始服务器,比较安全,负载均衡(当很多用户访问资源服务器时,让不同的代理服务器发送不同的资源)

实现方式优点缺点
Jsonpscript标签的src="www.baidu.com/json/?callb…func", 通过script标签请求时,后端会根据响应的参数(json, func)生成相应的json数据func({ "data": "zhe" }), 这个json数据就会被放到当前的js文件中执行1、只能使用get请求2、jsonp是从其他域中加载代码执行,容易受到跨站请求伪造的攻击,安全性不高3、不能注册success/error事件,无法确定请求是否成功
Corscross-origin resource sharing 跨域资源共享服务器添加响应头1. Access-Control-Allow-Origin: * 服务器设置第一条即可
  1. Access-Control-Allow-Methods: POST, GET, OPTIONS
  2. Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
  3. Access-Control-Max-Age: 86400默认不会携带cookie,如果要带cookie1. "Access-Control-Allow-Credentials": true
  4. // Ajax设置
  5. "withCredentials": true | | 不能修改cookie中的domain信息,不方便当前的cookie的写入,所以不饿能进行登录认证 | | WebSoket | 是一种浏览器的API,目标是在一个单独的持久连接上提供全双工,双向通信;js创建soket后,会有一个http请求发送到浏览器以发起连接,服务器响应后,建立的连接会从http协议升级到web soket协议 | | | | webpack反向代理 | 通过设置devServer的proxy的target:"xx.xx:3000", 客户端发出请求,先到代理的中间层,将本地的域名包装成目标域名,再发送给服务器,服务器返回数据,也是先到代理的中间层,把目标域名包装成本地的域名 | | | | H5新引进的window,postMessage | | | | | Document.damain | | | | | Location.hash | | | | | Window.name | | | | | Nginx反向代理 | | | |

Promise

        是解决异步的,有三种状态,pending进行中, resolved已完成, rejected已失败;状态一旦改变,就无法再次改变状态

        缺点:

               1、回调地狱;2、嵌套导致代码可读性差;3、promise一旦执行,无法中途取消;4、如果不设置回调,promise内部的错误无法反应到外部

        缺点解决方案:

               1、setTImeout设置并不立刻执行;2、事件监听,表示某个事情发生才会触发;3、async/await

        如何使用:

               1、创建promise实例/1、再用then方法指定resolved和rejected状态的回调函数/3、用try,catch方法捕获异常

        兼容老旧浏览器没有Promise对象:

               使用est-promise-polyfill 可以使用页面标签直接引入,es6/import, node/require,会在window对象中引入promise对象

        异步无论成功失败,都调用一个方法:

               promise.finaly = func,  内部也可以return一个promise对象,继续调用其他方法


http1、http2、https、状态码:版本区别

         http用的端口是80,https是443;http协议运行在tcp之上,所有传输的内容都是明文,https运行在ssl/tls(安全传输协议)之上,而ssl/tls运行在tcp之上,所有传输内容都是加密的;https需要申请证书,需要交费

         http1:线程阻塞,同一时间,同一域名的请求有一定数量限制,超过限制会被阻塞;tcp连接里,按次序进行,浪费带宽

         http2:多路复用,而非有序阻塞的;采用二进制格式而非文本格式;报头压缩;服务器推送,安全协议层,https

         状态码:

********1开头开始请求;

         2开头请求成功;200成功

         3开头重定向;301网址发生改变,自动转到新位置;302临时移动;304资源未改过,服务器不会返回任何内容;305请求者只能使用代理访问请求的网页;307临时重定向

         4开头请求报错;400服务器不解,请求语法错误;401需要身份验证;403服务器拒绝请求;404服务器找不到请求的网页;405禁用请求中指定的方法

         5开头服务器报错;500服务器内部错误;501服务器无法识别请求方法;502网关错误;503服务不可用;504网关超时;505http版本不受支持


浏览器的缓存

         缓存机制:

                当查找缓存都没有的时候,才会去请求,缓存查找顺序如下:service worker,memory cache, disk cache, push cache

         service worker:  它涉及到请求拦截,所以都用https,它可以自由控制缓存哪些文件,如何匹配、读取缓存;需要先注册Service worker,然后监听install事件后可以缓存需要的文件,下次访问可以通过拦截请求,查看是否存在缓存,如果有,直接读取缓存,否则请求数据

         memory cache是内存中的缓存,主要包含当前页面中已经抓取到的资源,比如样式,图片等等,关闭页面后,缓存消失

         disk cache是硬盘中的缓存,读取速度慢,但容量和存储时效性较强,它会根据http header的字段判断哪些需要缓存,哪些可以直接使用,哪些需要重新请求,跨站点情况下,相同地址资源如果被硬盘缓存下来,就不会再请求

         push cache 推送缓存是http/2中的,以上三中都没有,它才会被使用

         HTTP缓存:分为强缓存和协商缓存,强缓存失败时,才走协商缓存

         强缓存:根据http头中的expires和cache-control字段控制,如果有直接从缓存中获取资源,不会请求。

                        服务器返回响应中,在response headerzhong 设置expires字段,当再次请求时,如果本地时间小于expires时间,就读取缓存资源

         协商缓存:浏览器需要向服务器询问缓存相关信息,再判断是否重新发起请求,如果服务器提示缓存资源没有改,资源被重定向到浏览器缓存(304状态码)

                        服务器返回响应中,设置last-modified,随后每次请求,都会带上if-modified-since字段,它的值是上一次请求返回的last-modified,服务器对比,if-modified-since === last-modified, 如果不一样,就会返回完整的响应内容,在response header中添加新的last-modified, 如果一样,返回304, response header不会再添加last-modied字段

          缓存使用场景:

          1、打开网页,输入网址:查找disk cache是否有匹配,如果有就用, 没有就发请求

          2、刷新(F5):t因为ab没有关闭,所以,memory cache被优先匹配,然后disk cache

          3、强制刷新(Ctrl+F5):浏览器不适用缓存,因此请求头都带有cache-control:no-cache

         怎么设置缓存?

          cookie:辨别用户身份,在http请求在头部发给服务端

          sessionStorage:浏览器关闭会全部删除

          localStorage:.setItem(key,value) 设置记录;.getItem(key)获取记录;.removeItem(key)删除单条记录;.clear()删除所有记录;

          application cache离线存储:将大部分图片资源、js、css放在manifest文件配置中,当页面打开时,通过manifest文件来读取本地文件或是请求服务器


Url输入后发生什么

         首先会去缓存中查找,是否与要找的相匹配的资源,如果有,从缓存中拿资源,如果没有通过dns将url解析成对应的ip地址,与ip地址对应的服务器建立tcp连接,随后我们向服务端发出http请求,服务器处理完,把数据放在http响应里返回给客户端,浏览器渲染页面:

         浏览器缓存——系统缓存——路由器缓存

         1、DNS解析;解析ip时,首先向本地dns发出请求,如果找不到,依次向根服务器、顶级域名服务器、权限服务器得到ip,本地dns将ip发回给浏览器,浏览器向ip发出请求

         2、TCP连接(三次握手);客户端携带个什么包给服务端;服务端接受,服务端带x包给客户端;客户端接受

         3、HTTP请求;

         4、服务器响应,数据返回;

         5、浏览器拿到响应数据,解析,渲染页面


Ajax、axios、fetch:区别、特点、原理、优缺点、流程

定义: Asynchronous javaScript and XML

优点:不刷新整个页面的情况下与服务器通信保持原有页面状态;异步的

缺点: ajax逻辑会把对客户端的安全扫描技术隐藏起来,允许黑客从远程服务器上建立新的攻击,例如跨站点脚本攻击,SQL注入攻击

$ajax参数:

  • url: 请求地址;  
  • type: 请求类型,
  • get/post;  
  • timeout:设置请求超时的毫秒数;
  • async 为true, 所有请求为异步,false是同步;
  • data: 发送到服务器的数据,参数;

过程:

  • 创建对象,打开浏览器; var xhr = new XMLHttpRequest
  • 输入地址:             xhr.open(‘post’, ‘1.text’, true)
  • 发送请求:              xhr.send()
  • 等待服务器返回内容:    xhr.onreadystatechange = function () { if (xhr.readyState === 4) {        if (xhr.status ===200 ){                alert(xhr.responseText)                                 } else {                                      alert(‘出错了’)                                  }

ajax创建:

  • 异步向服务器发送请求数据;
  • 创建XMLHttpRequest异步调用对象;
  • 创建HTTP请求,指定方法、url及验证信息;
  • 设置响应HTTP请求状态变化的函数;
  • 发送;
  • 获取异步返回数据;
  • 局部刷新;

ajax、axios、fetch优缺点:

fetch:

缺点:

  • fetch只对网络请求报错,对400500都当做成功的请求,需要封装去处理
  • fetch默认不会带cookie,需要添加配置项。
  • fetch不支持abort中断,不支持超时控制,使用setTimeoutPromise.reject的实现超时控制并不能阻止请求过程继续在后台运行,造成了流量的浪费。
  • fetch没有办法原生监测请求的进度,而XHR可以。

优点:

  • 更加底层,提供的API丰富(request, response)
  • 脱离了XHR,是ES规范里新的实现方式
  • 跨域处理(mode为"no-cors")

axios:

优点:

缺点

  • 从浏览器中创建XMLHttpRequests
  • 从 node.js 创建 http 请求
  • 支持 Promise API
  • 拦截请求和响应
  • 转换请求数据和响应数据
  • 取消请求
  • 自动转换 JSON 数据
  • 客户端支持防御 XSRF
  • 只持现代代浏览器.

ajax:

优点

对原生XHR的封装,做了兼容处理,简化了使用。 增加了对JSONP的支持,可以简单处理部分跨域。

缺点

  • 如果有多个请求,并且有依赖关系的话,容易形成回调地狱。
  • 本身是针对MVC的编程,不符合现在前端MVVM的浪潮。
  • ajax是jQuery中的一个方法。如果只是要使用ajax却要引入整个jQuery非常的不合理。

React-router、router、hash、history的原理使用

React-router原理:

  • 在history库的基础上实现了URL与UI的同步
  • 监听url的变化,匹配路由规则,显示相应的页面,而且无需刷新页面跳转;

实现方式:

  • hash模式:www.test.com/#/  就是hash url, #后面哈希值变化时,通过hashchange事件监听url变化,跳转页面;
  • history模式: 使用history.pushState和history.replaceState改变url,不会刷新页面,只会更新浏览器历史记录;

两种对比:

  • history可以通过api添加任意类型的数据到历史记录中,在用户手动输入地址或者刷新页面时会发起url请求,后端需要配置index.html页面用户匹配不到静态资源的时候;
  • hash只能更改哈希值,hash无需后端配置,兼容性好;

React-router原理: 实现URL与UI界面的同步;URL=》location,UI=》component;

具体实现:

  • Router与route的区别:
  • Route:是进行url和函数的映射;
  • Router:在接收到一个url后,去路由映射表中查找相应的函数;
  • 客户端路由:路由的映射函数通常进行一些DOM的显示和隐藏操作;基于Hash(#及其后),History API两种方法;
  • History三种形式:browserHistory、hashHistory、createMemoryHistory;

react-router依赖的基础是History,是个独立的第三方js库,兼容在不同浏览器、不同环境下对历史记录的管理,拥有统一的API。具体来说里面的history分为三类:

老浏览器的history:  主要通过hash来实现,对应createHashHistory利用HTML5里面的history  pushState、replaceState 高版本浏览器: 通过html5里面的history,对应createBrowserHistory 通过hash来存储在不同状态下的history信息  location.hash=*** location.replace()

node环境下:  主要存储在memeory里面,对应createMemoryHistory在内存中进行历史记录的存储


兼容性问题: 浏览器、前端

浏览器兼容性问题IE相关兼容性css兼容性
img相关图片IE中有边框: img { border: 0/none } 图片下方3像素缝隙:img { display: block }或者img { vertical-align: top/middle }默认高度(IE7及以下版本)部分块元素默认高度(16px左右)没有高度,要设置height: 0;!important不推荐,
表单相关表单元素距离底部间距不一致: input { float: left }浮动元素双倍边距(IE6中)浮动元素,margin加倍显示:display: inlineflex
透明度其他浏览器:opacity: 0-1;IE写法:opacity:0-1; filter: alpha(opacity = 50)input去掉默认边框,不能设置border:none(IE6及以下)border: 0;css3属性
浏览器默认的margin和padding不同*{ margin: 0; padding: 0; }按照四舍五入解析百分比,容易大于100%给右侧浮动元素: clear: right;
  • safari中伪元素不支持CSS3动画
  • safari中元素高度为0,直接被忽略,在IE/chrome中都是作为块级看待,有相应的位置
  • IOS系统中,浏览器只支持给原生HTML按钮或《a》标签加js事件
  • Safari中Date.parse()解析时间字符串,格式必须是YYYY/MM/DD HH:MM:SS
  • IOS系统中,H5播放器不支持自动播放
  • 用原生js写粘贴复制到剪贴板的时候,采用了很多方法,比如document.execCommand(‘copy’) 写了很多形式,就是不好使,后来google搜索才知道,不兼容chrome,只支持IE,这个浪费了很多时间,影响开发效率,百度搜索的问题;
  • PropTypes不好用的时候,把import PropTypes from 'react' 写成 import PropTypes from 'prop-types' ,把defaultPropTypes 改成 propTypes
  • 开发过程中,遇到了一个常见的兼容性问题: IOS不识别 ' 2018-12-13 '中的 ' - ',需要转为2018/12/13的形式才可以识别;
  • 开发过程中,写了两个定时器,在两个定时器需要在某个条件下,替换的时候,需要clearInterval清除定时器,要不然会出现,每秒会相继执行两个定时器的现象;
  • 不要在componentWillRecivieProps里使用setState, 如果要使用,需要判断结束条件,不然会出现无限重渲染,导致页面奔溃;
  • 画布节点拖拽卡顿,用的lodash的throttle方法控制节流,减少setState的次数;
  • 前端用的是history跳转的,但是url地址页面一刷新就报错,后来后端那边设置了一判断处理,才可以的;

线程、进程

进程: 一个完成的任务;比如,调用数据库

线程: 完成这个任务的诸多子任务之一;比如要从数据库中产生一份统计表,上传到某文件;

一个线程只属于一个进程,一个进程可以有多个进程;

线程好处:提高并发性;


节流、防抖

名称原理适用场景实现
防抖当事件触发n秒后执行回调,如果在n秒内又被触发,则重新计时.1.按钮提交场景:防止多次提交,只提交最后一次. 2.搜索框联想场景:防止联想发送请求,只发送最后一次输入.1.非立即执行 2.立即执行
节流规定在一个单位时间内只能触发一次函数.如果在单位时间内触发多次,只执行一次.1.拖拽场景:固定时间只执行一次,防超高频次触发. 2.缩放场景:监控浏览器resize,scroll1.时间戳实现 2.定时器实现

节流实现:                                                                                               防抖实现:

​编辑   


垃圾回收、内存泄漏、call/applay

内存泄漏:

  • 闭包return 给window;
  • 未声明的全局变量;
  • 定时器没有及时clear;
  • vue 中在mounted/created 用$on;
  • 给DOM对象添加的属性时一个对象的引用;
  • DOM对象与JS对象相互引用;
  • 反复写同一个属性会造成大量内存占用;

避免内存泄漏: 

     尽量少使用闭包;及时删除监听器;

垃圾回收机制:

     垃圾回收器根据根开始标记,然后访问并标记来自他们的引用,直到有未访问他们的引用为止,删除所有没标记的对象;

call/apply:

     call:  参数逐个列举

     apply: 参数数据


事件委托、事件监听、事件处理函数、作用域、声明提升

函数声明提升权重大于变量声明提升,函数有声明提升,函数表达式没有声明提升

事件委托/代理:

  • 利用事件冒泡原理,让自己所触发的事件,让父元素代替执行;

实现原理:

  • event.target监听实际触发元素;避免是期望元素的子节点,需追加parentNode循环判断。

好处:

  • 提高性能、提高事件的处理速度,减少内存占用;
  • 动态添加DOM元素,不要因为元素的改动而修改事件绑定

事件监听:

  • 有三个阶段,捕获、目标、冒泡;
  • 优点:可绑定多个事件,可解除相应的绑定

事件处理函数:

  • 处理用户操作的函数,不同操作,不同名称;

方法:

  • DOM直接绑定,比如onCLick;
  • 在javaScript代码中绑定;
  • 绑定事件监听函数,比如addEventListner()、 attachEvent();

作用域:

  • 全局作用域、函数作用于、eval作用域;没有块级作用域;

作用域链:

  • 当函数被创建,就有了作用域,当被调用,就有了作用域链,当被继承,就有了原型链,当需要获取作用域链或原型链上的变量或值时,就有了闭包;

继承、闭包、原型、原型链、面向对象、循环

闭包:

  • 定义:能读取其他函数内部变量的函数
  • 作用:读取函数内部变量的值
  • 缺点: 变量是保存在内存中,内存消耗大,所以会造成网页的性能问题;
  • 解决/注意:在退出函数前,将不适用的变量全部删除;

继承:

  • 定义:子类有父类的所有属性和方法
  • 优点: 抽取重复代码,减少代码冗余
  • 缺点: 代码耦合性太强

   继承方式:

  • 构造函数式:借用call或apply方法,把父类构造函数复制继承到子类上,子类new出的实例,就是把父类构造函数的内容copy到实例中,所以每个实例都是独立的,私有的;

       缺点:只实现属性的私有,没有实现方法共享

  • 原型链式: 借用js对象的特性,对象在寻找自己属性时,先在当前对象上找,没有,再去自己原型链上找,一直向上找直到null

       好处:节省内存

       缺点:属性和方法全部都被共享了

  • 组合式(原型链+构造函数): 基本属性放父类的构造函数里;共享的函数方法放在父类原型上

       优点:实现函数共享,属性私有

  • Object.create()寄生式
  • 寄生组合式

面向对象:

三大特征:

  • 继承;目的: 实现代码复用;注:父类的私有属性private和构造方法不能被继承;子类可以写自己特有属性和方法,实现功能的扩展,子类可以复写父类的方法;protected属性对外界隐藏,允许子类访问;
  • 封装;目的: 增强安全性和简化代码,使用者不需要了解具体实现细节,只要通过外部接口,来使用;
  • 多态;可扩展,增强维护性;

创建对象的方式:

  • 对象字面量:var a={}
  • 用面向对象的方法: var obj=new Object()
  • 构造函数方式 function Abc(){} var c=new Abc() 构造函数首字母大写 优化:把方法放在原型上,,把属性放在构造函数上,把共有属性放在init方法函数中,也在放到原型上,这样避免内存浪费,方法可以共有;

创建对象的模式:

  • 工厂方式
  • 构造函数方式

声明组件的方式

  • 无状态组件,又叫纯组件SFC
  • React.creactClass
  • React.component   ES6 class…extends

ui组件负责ui的呈现,容器组件负责管理数据和逻辑;二者通过react-redux提供的connect方法联系起来;

调用super(props)之前,子类不能使用this, 调用super(props)便于子类在constructor中访问this.prps;


有无状态组件、受控非受控组件:

有状态组件无状态组件受控组件非受控组件
在内存中存储有关组件状态变化的信息计算组件的内部的状态没有维持自己的状态保持自己的状态
可以改变状态不能改变状态数据由父组件控制数据由dom控制
包含过去,现在,未来可能的状态变化情况不包含过去,现在和未来可能发生的状态变化情况通过props获取当前值,通过回到通知更改refs用于获取当前值
接受无状态组件状态变化要求的通知,然后将props发给他们从有状态组件接受props并将其视为回调函数

判断一个类是否继承另一个类的方法


Webpack、gulp:区别、特点


前端优化、react优化、vue优化、性能优化、webpack优化

前端优化webpack优化react优化vue性能优化
加快首屏渲染非核心代码异步加载脚本async:加载完后立即执行,如果是多个,执行顺序和加载顺序无关开发阶段的构建性能:减少模块解析:如果模块中没有其他依赖,比如打包好的第三方库jq,就不需要解析,在module中设置noParse: /jq/优化loader性能;避免重复渲染;shouldComponentUpdate判断是否执行render
资源合并压缩合并图片,css,js文件,压缩js: UglifyPlugin; css: MiniCssExtractPlugin;Html:HtmlWebpackPlugin现流行gzip压缩,在http请求头中Accept-encoding添加gzip标识,需要服务器支持这一功能,提交可以较少50%左右图片较多的使用懒加载优化提取第三方库:webpack4的splitChunk插件cacheGroups选项使用cdn引入,jq、echarts这种库将资源下载到服务器引入:webpack配置externals: {   jquery: ''$',  echarts: 'echarts',}useMemo指定依赖项,变化时才计算const result = useMemo(()=>computeExpensiveFunc(start), [start]);
减少http请求次数和请求时间一个域名对应多个相同服务的ip服务端给客户端传输性能,代码少,时间少,文件越少,http请求越少合理使用useCallback组件绑定的函数在每次render都是新生成的,所以使用useCallback并添加依赖项
使用cdn解析ip时,向本地dns发请求;本地dns向根、顶级域名、权限服务器发请求,得到全局负载均衡系统(gslb)的ip地址;本地dns向gslb发请求,gslb根据本地dns的ip地址判断用户的位置,筛选距离用户最近的本地负载均衡系统(slb),gslb将slb的ip发给本地dns;本地dns发给浏览器,浏览器向slb发请求;slb选出最优的缓存服务器发给浏览器;浏览器根据slb发回的地址重定向到缓存浏览器;缓存浏览器如果有资源,发给浏览器,没有就向源服务器请求资源,再发给浏览器并缓存在本地;体积优化,代码压缩,插件使用:optimization: { minimize: true, minimizer: {   new OptimizeCssAssetsPlugin()}}js: UglifyPlugin;css: MiniCssExtractPlugin;Html:HtmlWebpackPlugin;gzip,是一种压缩文件的算法,文件过大就可以用它压缩, 在http请求头中Accept-encoding添加gzip标识,需要服务器支持这一功能,提交可以较少50%左右;懒加载;谨慎使用context,它是跨组件传值,所以无法阻止context触发的rendercontext只放在必要的关键的,被大多数组件共享的状态建议在负极获取context数据,通过props传递
利用浏览器缓存强缓存:不请求,直接使用本地缓存协商缓存:1、第一次请求资源,服务器返回,带上last-modifiedhed在response header中,浏览器再次请求时,会在requset中家加上if-modified-since = last-modified,服务器对比,没变化返回304,有变化,就返回资源内容2、Etag、if-none-match第一次请求,服务返回Elag,字符串,资源有变化,Etag就不同,再次请求时,加if-none-match = Etag, 服务器对比,没变化,返回304,有变化,返回资源内容热更新webpack-dev-server:代码变动时,浏览器会刷新,重新请求所有资源,但使用热更新后,代码修改时,浏览器不刷新,局部进行替换,devServer: { hot: ture }plugins: [new webpack.HotModuleReplacementPlugin()]写入文件中if (module.hot){ module.hot.accept() }热更新原理:webpack-dev-server会向打包结果注入module.hot属性,正常情况下,不管是否有热更新,重新打包都会调用location.reload刷新页面,但如果执行module.hot.accept()就不会调用它了,而是使用websoket的方式,将新内容传给浏览器,只是修改的部分,然后将结果交给插件hotModuleReplacementPlugin注入的代码执行,它会覆盖原始代码,重新执行redux使用要小心,否则触发无用的render​编辑
css放文件头部,js文件放底部第一时间加载可以看到样式,js也可以放在头部,加上defer属性,异步下载,延迟执行异步处理loader,减少处理时间;thread-loader会把loader放在一个线程中运行,提高构建效率操作redux源数据时,数组或对象地址是引用类型,如果直接操作,array.push(xx), 这样不会改变数据的地址,是直接修改的是地址指向的堆中的真实数据,仍然是相等的
图片延迟加载页面中,先不给图片设置路径,当图片出现在可视区域时,才去加载真正的图片尽量少的使用不同的工具:plugin加载都有启动时间
减少重排重绘回流(重排):改变dom元素位置、大小、内容改变,添加删除dom元素,浏览器窗口尺寸改变,需要重排,重排一定需要重绘;重绘:重新绘制界面,样式改了,需要重绘,重绘不一定重排减少方法:1、用js修改样式时,不用直接写样式,替换class修改样式2、将dom脱标,减少编译的大小:使用更小、更少的库多页面应用程序中使用commonChunkPlugin多页面以async使用commonCHunckPlugin移除不使用的代码: tree shaking,(webpack2开始支持) 生产环境自动开启,但没有提供普通的es6方式导入,通过commonjs方式导出的,无法发回作用只编译当前正在开发的代码tree shaking原理:webpack从入口开始寻找依赖关系,解析模块时,根据es6模块导入语句来判断,谁依赖谁,根据导出是否被使用,标记未使用的导出为dead code,然后交个代码压缩功能句处理,它会移除
少些if-lese-,用switchif else 会执行多次判断,switch只需要一次dllPlugin和ddlReferencePlugin拆分bundles提升构建速度,将一些不常更新的依赖提前打包引入entry: {vendor: ['react, 'redux', 'react-router',‘axios’,]}plugin: [ new webpack.DllPlugin({ name: 'xx' 需要和outPut内的liabrary保持一致 patch: patch.resolve(_dirname, 'dist', 'mainfest.json')  生成mainfest.json文件,})]

算法、排序

基本排序:

  • 冒泡排序:从头开始,两个两个互相比较,小的放前面;      
  • 选择排序:从头开始,第一个数与后面所有相比,最小的放第一个位置;
  • 插入排序: 第一个放哪里无所谓,接下来比第一张小,放左边,依次进行;

高级排序:

  • 快速排序:采用递归方式,随意找到一个数,小的放前面,大的放后面,分别对前后做相同的操作比较;
  • 希尔排序:插入排序的改良算法,但与其核心概念不同,先从比较远的开始比较,小的放在前面;

高阶函数(HOC)

参数为一个组件,返回为一个组件


Amd/Cmd

两者对模块执行时机不同:

       AMD(require.js):  加载完模块,立即执行;

       COD:不会立即执行,等到遇到require才执行


单页面应用(SPA)、优缺点、实现方式

        单页面应用(SPA):只有一个主页面的应用,所有页面内容都包含在这个所谓的主页中,在交互的时候,由路由程序动态载入,单页面跳转,仅仅刷新局部资源,多用于pc端

        多页面应用(MPA):一个应用中有多个页面,页面跳转的时候,整页进行刷新

        单页面缺点:    没有前进和后退功能,需要自行实现前进后退

        


Git

        git常用命令

              git  log 查看日志                  git   add .    提交当前目录全部文件            git  reset   --hard   xxx    本地回退到某版本

              git status 查看冲突              git   commit -m    提交到本地                     git  rm xx  删除文件

              git diff  查看修改                  git push origin xx  提交到远程                    git  checkout -b 新建分支

              git  branch 查看分支            git branch -D 删除本地分支                        git push origin --delete xx  删除远程分支

              git  stash  暂存区                 git stash pop 回复暂存区的代码删除暂存


网络安全、xss攻击

     xss攻击:跨站脚本攻击,攻击者在另外一个用户的浏览器中执行恶意代码脚本注入

     持续性攻击:通过表单提交、评论方式将提交到网站,如果服务端没有做任何处理,直接把数据返回前端,前端展示在页面中,所有的用户打开页面,就会弹出这个弹框

     防止:校验用户输入和请求,客户端和服务端必须验证


小程序


Node


Js、d3、svg、echarts、highcharts、ant-g6、mxgraph


以上为个人查询文档资料思考所总结,如果错误,请各位大佬指正,非常感谢!以上多个部分还未完善,后续抽时间会继续补充完整