2021年高级前端进阶之路

YYDS 2021年高级前端进阶之路
  1.两边固定,中间自适应布局(1.用flex;2.用display:left;3.用相对定位和绝对定位结合)
  2.js判断字符串中出现次数最多的字符(1.用for循环将字符串字符和出现次数push到一个新对象中;2.在这个新对象中用for in进行比较,分别找出次数最多的字符和出现次数。)
  3.Vue.set的用法及场景(1.vue中检测不到对象属性的添加和删除;2.通过数组的下标去修改数组的值,数据已经被修改了,但是不触发updated函数,视图不更新。原理:vue.$set是能让vue知道你添加了属性, 它会给你做处理。)
  4.Vue自定义指令的钩子函数及使用场景 
    4.1 钩子函数:bind,inserted,update,componentUpdated,unbind)
    4.2 函数参数:el,binding,vnode,oldVnode
    4.3 使用场景:按钮级别的权限控制
  5.Vue页面渲染过程 (
    5.1 加载文件执行顺序:1.打包配置位置;2.index.html;3.main.js;4.路由文件,将组件渲染到router-view;5.router-view中加载layout;6.Layout加载Navbar,Sidebar,AppMain
    5.2 Vue内部页面执行顺序:1.把模板编译为render函数;2.实例进行挂载,根据根节点render函数的调用,递归生成虚拟DOM;3.对比虚拟DOM,渲染到真实DOM;4.组件内部发生变化,data作为props重新调用render函数,生成虚拟DOM,重复第3步.
  6.React Hooks 
    6.1 为何用hooks(1.组件之间的逻辑状态难以复用;2.大型复杂组件难以拆分;3.Class语法的使用不友好)
    6.2 hooks优点(1.没有破坏性改动,完全可选;2.更容易复用代码,复用状态;3.函数式编程风格,清爽优雅;4.代码量少;5.更容易拆分)
    6.3 hooks缺点 (1.是React16.8版本的新增特性;2.因为闭包造成状态不同步;3.数组的push,pop,splice方法直接改变原数组,使用useState无法获取更新;4.useState初始化只初始化一次;5.useEffect内部不能修改state;6.useEffect依赖引用类型会出现死循环;7.不要在循环,嵌套,条件函数中调用hook,会产生顺序不一致问题)
    6.4 解决闭包的坑 (闭包造成每次输出原来的state。可以通过useRef来保存state)
    6.5 常用的Hooks有哪些 (1.useState()状态钩子;2.useContext()共享状态钩子;3.useReducer()状态钩子,很像redux;4.useEffect()副作用钩子,两个参数,一个是异步操作,一个是数组依赖项;5.useRef()获取组件实例,渲染周期之间共享数据的存储;6.useMemo缓存数据,useCallback缓存函数,常见的优化策略)
      useCallback(fn,deps)相当于useMemo(()=>fn,deps),经常用在下面两种场景:
        6.5.1 要保持引用相等;对于组件内部用到的 object、array、函数等
        6.5.2 用在了其他 Hook 的依赖数组中,或者作为 props 传递给了下游组件,应该使用 useMemo/useCallback)
    6.6 useEffect为什么有时候会出现无限重复请求的问题 (可能1.未设置依赖参数,每渲染一次就触发一次;可能2.所设置的依赖项总是会变。解决:useCallback包一层,或者useMemo)
    6.7 使用hooks模拟生命周期 (可以封装一个模拟的js,然后各处都可以调用)
      6.7.1 使用useState模拟constructor 代码:const [count, setCount] = useState(0)
      6.7.2 使用useEffect模拟componentDidMount 代码:useEffect(() => { fn() }, [])
      6.7.3 使用useMemo模拟shouldComponentUpdate  代码:React.useMemo((props) => {// your component})
      6.7.4 使用useEffect+useState模拟componentDidUpdata 代码:useEffect(() => fn() ));
      6.7.5 使用useEffect模拟componentUnMount 代码:useEffect(() => fn(), [])
    6.8 模拟的生命周期和class中的生命周期有什么区别 (1.默认的useEffect(不带[])中return的清理函数,默认情况下在每次useEffect执行前都会执行,并不是只有组件卸载的时候执行; 2.useEffect在副作用结束之后,会延迟一段时间执行,并非同步,和compontDidMount有本质区别。遇到dom操作,最好使用useLayoutEffect。)
    6.9 Hooks相比HOC和Render Prop有哪些优点?(1.hoc和render prop都是一种开发模式,将复用逻辑提升到父组件,容易嵌套过多,过度包装;2.hooks是react的api模式,将复用逻辑取到组件顶层,能够避免 HOC 和 Render Props 带来的「嵌套地狱」。)
    6.10 Function Component与Class Component区别 
      6.10.1 对于class component来说:(1.首先state是不可变(Immutable),setState后生成一个全新的state引用;2.通过this.state方式读取state,所以每次代码执行都会拿到最新的state引用。)
      6.10.2 对于function component来说:(1.useState 产生的数据也是不可变 Immutable 的,通过数组第二个参数 Set 一个新值后,原来的值在下次渲染时会形成一个新的引用。2.但它state没有通过this.的方式读取,每次执行都读取当时渲染闭包环境的数据,虽然最新的值跟着最新的渲染变了,但旧的渲染里,状态依然是旧值。)
      6.10.3 原理:function组件能捕获渲染的值(captaure the rendered values),读取渲染闭包内的数据,而class组件在react通过this.的方式读取,this是可变的,所以总能获取最新的props。
      6.10.4 保存状态:Class把state属性挂载的对象保存到memoizedState属性中,而Function是用链表来保存状态的,memoizedState属性保存是链表的头指针。
    6.11 useEffect和useLayoutEffect区别
      6.11.1 useEffect是render结束后,callback函数执行,但是不会阻断浏览器的渲染,算是某种异步的方式吧,大部分场景下都比class的同步方式性能更好。
      6.11.2 useEffect里面的操作需要处理DOM,并且会改变页面的样式,就需要用这个,否则可能会出现出现闪屏问题, useLayoutEffect里面的callback函数会在DOM更新完成后立即执行,但是会在浏览器进行任何绘制之前运行完成,阻塞了浏览器的绘制。
    6.12 setState和useState区别 (1.setState是通过回调函数来获取更新的state,useState是通过useEffect() 来获取最新的 state;2.二者第一个参数都可以传入函数;3.setState()可以在第2个参数传入回调,useState()没有第2个参数;4.setState()自动具备浅合并功能,useState()更新引用需要手动浅合并)
    6.13 useState中的第二个参数更新状态和class中的this.setState区别 (1.useState 通过数组第二个参数 Set 一个新值后,新值会形成一个新的引用,捕获当时渲染闭包里的数据 State;2.setState 是通过 this.state 的读取 state,每次代码执行都会拿到最新的 state 引用)
    6.14 useReducer和redux区别
      6.14.1 useReducer() 提供了状态管理,其基本原理是通过用户在页面中发起action, 从而通过 reducer方法来改变state, 从而实现页面和状态的通信,使用很像redux。
      6.14.2 useReducer是useState的代替方案,用于state复杂变化
      6.14.3 useReducer是单个组件状态管理,组件通讯还需要props,redux是全局的状态管理,多组件共享数据
    6.15 Hooks性能优化 (1.useMemo 缓存数据;2.useCallback 缓存函数;3.相当于class组件的SCU和PureComponent)
    6.16 怎么在高阶组件里面访问组件实例 (1.属性代理。高阶组件通过包裹的React组件来操作props,更改 props,可以对传递的包裹组件的WrappedComponent的props进行控制。2.通过 refs 获取组件实例。)
  7.promise关于宏任务和微任务 (1.主线上的同步任务先执行,然后再执行微任务,最后是宏任务;2.(特殊情况): 一般都是微任务先执行,然后再执行宏任务,但是在promise里面的宏任务函数,必须先执行完,才能往下执行。)
  8.redux与react-redux的区别 
    8.1 简介:(1.redux是react中进行state状态管理的JS库(并不是react插件),一般是管理多个组件中共享数据状态。这个是和Vuex是一样的。2.React-Redux是Redux的官方React绑定库。它能够使你的React组件从Redux store中读取数据,并且向store分发actions以更新数据。)
    8.2 区别:
      8.2.1 redux和组件进行对接的时候是直接在组件中进行创建。react-redux是运用Provider将组件和store对接,使在Provider里的所有组件都能共享store里的数据,还要使用connect将组件和react连接。
      8.2.2 获取state的方式不一样;redux获取state是直接通过store.getState()。react-redux获取state是通过mapStateToProps函数,只要state数据变化就能获取最新数据。
      8.2.3 触发action的方式不一样;redux是使用dispatch直接触发,来操作store的数据。react-redux是使用mapDispathToProps函数然后在调用dispatch进行触发。
  9.简述Redux
    9.1 redux主要由三部分组成:store,reducer,action。
    9.2 store是一个对象,它有四个主要的方法:dispatch用于action的分发;subscribe监听state的变化;getState获取store中的state;replaceReducer替换reducer,改变state修改的逻辑。
    9.3 action是一个对象,其中type属性是必须的,同时可以传入一些数据。action可以用actionCreactor进行创造。dispatch就是把action对象发送出去。
    9.4 reducer是一个函数,它接受一个state和一个action,根据action的type返回一个新的state。根据业务逻辑可以分为很多个reducer,然后通过combineReducers将它们合并,state树中有很多对象,每个state对象对应一个reducer,state对象的名字可以在合并时定义。
  10.简述http三次握手
    10.1 客户端发起一个创建连接的数据包的请求。
    10.2 服务端接收到这个数据包。就会开启一个TCP socket的端口,端口开启以后返回给客户端。
    10.3 客户端拿到了。继续返回。
    10.4 为什么要有三次握手:防止服务端开启无用的连接。因为网络传输是有延时的,可以规避网络延时导致服务器额外的开销。
  11.谈一谈闭包
    11.1 闭包概念;闭包是指有权访问另外一个函数作用域中的变量的函数.
    11.2 闭包应用场景:(1.采用函数引用方式的setTimeout调用,代码:setTimeout(getAge,1000) 2.给对象设置私有变量,并且利用特权去访问私有变量; 3.封装相关功能集)
    11.3 闭包引发问题:(1.内存泄漏,解决方法是,在退出函数之前,将不使用的局部变量全部删除;2.this的问题,使用闭包有可能会意外改变this的值。)
  12.谈谈原型链
    12.1 所有的引用类型(数组、对象、函数)都有一个__proto__属性(也称隐式原型属性),属性值是一个普通的对象;
    12.2 所有的函数都有一个prototype属性(也称显式原型属性),属性值也是一个普通的对象;
    12.3 所有的引用类型(数组、对象、函数)的__proto__属性(即隐式原型属性)指向它的构造函数的" prototype " 属性值(即显显式原型)(===)
    12.4 当调取一个对象的属性时,会先在本身查找,若无,就根据 _proto_ 找到构造原型,若无,继续往上找。最后会到达顶层Object prototype,它的 _proto_ 指向null,均无结果则返回undefined,结束。由 proto 串起的路径就是『原型链』。
  13.谈谈React生命周期:
    13.1 组件将要挂载时触发的函数:componentWillMount
    13.2 组件挂载完成时触发的函数:componentDidMount
    13.3 是否要更新数据时触发的函数:shouldComponentUpdate
    13.4 将要更新数据时触发的函数:componentWillUpdate
    13.5 数据更新完成时触发的函数:componentDidUpdate
    13.6 组件将要销毁时触发的函数:componentWillUnmount
    13.7 父组件中改变了props传值时触发的函数:componentWillReceiveProps
  14.谈谈Vue的数据双向绑定原理
    14.1 vue2.0数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的。具体通过Object.defineProperty()的 set 和 get,在数据变动时发布消息给订阅者触发监听。结合监听器Observer,订阅者Watcher,解析器Compile实现最终效果。
    14.2 vue2.0中的Object.defineProperty缺点:(1.无法监控到数组下标的变化;2.只能劫持对象的属性,因此我们需要对每个对象的每个属性进行遍历)
    14.3 vue3.0用proxy取而代之,两个优点:(1.可以劫持整个对象,并返回一个新对象;2.有13种劫持操作)Proxy的核心优点是可以交由它来处理一些非核心逻辑(如:读取或设置对象的某些属性前记录日志;设置对象的某些属性值前,需要验证;某些属性的访问控制等)。 从而可以让对象只需关注于核心逻辑,达到关注点分离,降低对象复杂度等目的。
    14.4 Proxy是 ES6 中新增的一个特性,翻译过来意思是"代理"。外界对该对象的访问,都必须先通过这层代理拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。
  15.Vue3.0新特性 (PT组多自优)=>(PT组多自由)
    15.1 Proxy 响应式绑定,它劫持的是整个对象,自然对于对象的属性的增加和删除都能检测到。效率更高,性能更好,另外 Virtual DOM 更新只 diff 动态部分、事件缓存等,也带来了性能上的提升。
    15.2 Tree-Shaking Support(摇树优化).tree-sharking 即在构建工具构建后消除程序中无用的代码,来减少包的体积。Vue3.0 支持按需导入,只打包需要的代码。
    15.3 组合式 API.
      15.3.1 组合式API与选项式API,mixins,React Hooks的比较
        15.3.1.1 选项式 API 存在的缺陷。Vue2.x 中组件传统的 data,computed,watch,methods 写法,我们称之为选项式API(Options API )务复杂度越来越高,代码量会不断的加大;后续维护非常的复杂;代码可复用性也不高;
        15.3.1.2 与 mixins 的比较。(1.层级不同:组合式API与组件是嵌套关系,而mixin与组件是同层级关系;2.影响面不同:组合式API耦合性很低。而 mixins 是耦合在代码逻辑里,升级和维护埋下隐患。)
        15.3.1.3 与 React Hook 的比较,React Hooks简便了不少。(1.同样的逻辑组合、组件复用能力。2.只调用一次 setup 方法;3.更加符合 JS 直觉;4.没有闭包变量问题;5.没有内存/GC压力;6.不存在内联回调导致子组件永远更新的问题。)
      15.3.2 组合式 API 的使用.
        15.3.2.1 setup方法 (1.setup方法,所有的代码逻辑将在setup方法中实现,,包括 data、watchcomputed、methods 等,并且不再有this;2.会先执行setup方法,再执行兼容2.x的其他方法。3.setup方法在组件生命周期内只执行一次,不会重复执行。)
        15.3.2.2 生命周期钩子 (1.生命周期钩子放在跟 methods 同级属性下;2.需要先导入钩子,然后在 setup 方法中注册钩子回调,并且钩子命名也跟 React 保持一样;3.移除了 2.x 中的 beforeCreate 和 created 钩子,通过 setup 方法代替)
    15.4 多个根节点;Teleport将我们的模板渲染至指定 DOM 节点,不受父级 style 、v-show 等属性影响,但 data、prop 数据依旧能够共用的技术;类似于 React 的 Portal。
         是一个特殊的组件,它将呈现回退内容,而不是对于的组件,直到满足条件为止,这种情况通常是组件 setup 功能中发生的异步操作或者是异步组件中使用。
    15.5 自定义渲染 API。通过createRendererAPI 自定义渲染 API 将 Virtual DOM(虚拟DOM)和平台相关的渲染分离。极大丰富了 Vue 的使用场景。
    15.6 优化源码
      15.6.1 使用 monorepo 来管理源码.(1.Vue.js 2.x 的源码托管在 src 目录,Vue.js 3.0通过 monorepo 的方式根据功能将不同的模块拆分到 packages 目录下面不同的子目录中,每个 package 有各自的 API、类型定义和测试。)
      15.632 使用 Typescript 来开发源码.(1.Vue.js 2.x 选用 Flow 做类型检查;2.Vue.js 3.0 使用 TypeScript 重构了整个项目。TypeScript 提供了更好的类型检查,能支持复杂的类型推导;由于源码就使用 TypeScript 编写,也省去了单独维护 d.ts 文件的麻烦)
  16.node后端框架选择 
    16.1 Express是一款基于node.js以及ChromeV8引擎,快速、极简的JS服务端开发框架,它提供了用来开发强壮的web/移动应用,以及API的所有功能。并且开发人员还能够方便地为它开发插件和扩展,从而增加Express的能力。
    16.2 KOA框架由Express原班人马打造,它的核心是ES6的generator。KOA使用generator来实现中间件的流程控制,使用try/catch来增强异常处理,KOA框架本身非常小,只打包了一些必要的功能.
    16.3 Egg是基于koa,由阿里nodejs团队封装的企业级Web应用解决方案,以约束和规范化团队开发(提供基于Egg定制上层框架的能力;内置多进程管理;渐进式开发。Egg已经被用在阿里多条产品线(包括蚂蚁)上,已经证明它的安全和可靠性,可以放心用。)
    16.4 Nest是一个用于构建高效,可扩展的Node.js服务器端应用程序的框架。它使用渐进式JavaScript,内置并完全支持TypeScript(但仍然允许开发人员使用纯JavaScript编写代码)并结合了OOP(面向对象编程),FP(函数式编程)和FRP(函数式响应编程)的元素。
  17.前端工程化方案
    17.1 框架选择:(1.后端Nodejs框架:Koa2;2.前端框架: React+Redux;3.CSS处理: Less+Postcss;4.构建工具: Webpack+Babel;5.代码规范: Prettier)
    17.2 开发过程:(1.项目初始化:前端脚手架;2.react native方案;3.H5多页应用服务端渲染方案;4.PC 移动端适配方案;5.接口mock服务;6.项目文档)
    17.3 优化:(1.http2.0网络优化;2.SSR缓存方案)
    17.4 测试:(1.单元测试:Jest+Enzyme;2.生成截图: Chrome Headless)
    17.5 运维:(1.性能监控;2.异常报警;3.oss自动上传方案)
  18.Web动画实现
    18.1 CSS3动画: 书写简单,性能好
      18.1.1 transform变形:transform 包含了rotate(旋转)、scale(缩放)、translate(移动)、skew(扭曲)以及matrix(矩阵变形)。一般会结合transition来使用,使元素变形的过程变的平滑。
      18.1.2 Transition(过渡):CSS3中的transition是让元素的属性值在一定时间区间内平滑过渡,还可以定义变换速率。
      18.1.3 Animation(动画):补间动画是指我们定义好两个时间节点上元素的状态,中间元素变化的过程由计算机帮我们计算好。比如@keyframes swing{ 20%{} 40%{} 60%{} 80%{} to{} }
    18.2 JS动画: JS动画一般是通过定时器和计时器来实现元素属性的不断变化,这里一般常用的有jQuery的animate()方法。
    18.3 Canvas动画: Canvas动画也是不断的快速的在屏幕上绘制图像和清除屏幕,形成了动画.
    18.4 SVG动画:可以学习《SVG精髓》这本书.SVG内置了一些动画元素:animate,animateMotion,animateTransform,animateColor.尽量使用元素属性来进行SVG的动画制作,比如stroke-dasharry,stroke-dashoffset,可以实现描边动画
    18.5 Three.js为首的3D动画 Three.js是一个基于JavaScript,使用方便,运行在浏览器中的轻量级的3D框架,可以用它创建各种三维场景,包括摄影机,光影及材质等各种对象,并且提供了Canvas、SVG、CSS 3D及WebGL4中渲染器。
  19.响应式布局的核心(@media媒体查询)
    19.1 媒体类型:通常我们使用的都是彩色屏幕(screen),打印预览(print),其他的都很少使用.
    19.2 媒体属性:	
      19.2.1 width:浏览器窗口的尺寸(可加max min前缀). min-width:100px	  >=100px 	max-width:100px   <=100px
      19.2.2 height:浏览器窗口的尺寸(可加max min前缀).
      19.2.3 device-width:设备独立像素(可加max min前缀).pc端:分辨率.移动端:具体看机器的参数.
      19.2.4 device-pixel-ratio:屏幕可见宽度与高度的比率/像素比(可加max min前缀,需要加-webkit前缀).	pc端:1;  移动端:具体看机器的参数(DPR).
      19.2.5 orientation: portrait(竖屏) | landscape(横屏)
    19.3 操作符,关键字(1.only:和浏览器兼容性有关,老版本的浏览器只支持媒体类型,不支持带媒体属性的查询.2.and:代表与的意思,一般用and来连接媒体类型和媒体属性.3.or(,):和and相似.4.not:取反,类似JS里的!.)
  20.Web前端性能优化
    20.1 内容优化
      20.1.1 减少HTTP请求数:这条策略是最重要最有效的,因为一个完整的请求要经过DNS寻址,与服务器建立连接,发送数据,等待服务器响应,接收数据这样一个消耗时间成本和资源成本的复杂的过程。
          常见方法:合并多个CSS文件和js文件,利用CSS Sprites整合图像,Inline Images20.1.使用 data:URL scheme在实际的页面嵌入图像数据  ,合理设置HTTP缓存等。
      20.1.2 减少DNS查找
      20.1.3 避免重定向
      20.1.4 延迟加载组件,预加载组件
      20.1.5 减少DOM元素数量:页面中存在大量DOM元素,会导致javascript遍历DOM的效率变慢。
      20.1.6 最小化iframe的数量:iframes 提供了一个简单的方式把一个网站的内容嵌入到另一个网站中。但其创建速度比其他包括JavaScript和CSS的DOM元素的创建慢了1-2个数量级。
      20.1.7 避免404:HTTP请求时间消耗是很大的,因此使用HTTP请求来获得一个没有用处的响应(例如404没有找到页面)是完全没有必要的,它只会降低用户体验而不会有一点好处。
    20.2 服务器优化
      20.2.1 使用内容分发网络(CDN):把网站内容分散到多个、处于不同地域位置的服务器上可以加快下载速度。
      20.2.2 GZIP压缩
      20.2.3 设置ETag:ETags(Entity tags,实体标签)是web服务器和浏览器用于判断浏览器缓存中的内容和服务器中的原始内容是否匹配的一种机制。
      20.2.4 提前刷新缓冲区
      20.2.5 避免空的图像src
    20.3 Cookie优化
      20.3.1 减小Cookie大小
      20.3.2 针对Web组件使用域名无关的Cookie
    20.4 CSS优化
      20.4.1 将CSS代码放在HTML页面的顶部
      20.4.2 避免使用CSS表达式
      20.4.3 使用来代替@import
    20.5 javascript优化
      20.5.1 将JavaScript脚本放在页面的底部。
      20.5.2 将JavaScript和CSS作为外部文件来引用:在实际应用中使用外部文件可以提高页面速度,因为JavaScript和CSS文件都能在浏览器中产生缓存。
      20.5.3 缩小JavaScript和CSS
      20.5.4 删除重复的脚本
      20.5.5 最小化DOM的访问:使用JavaScript访问DOM元素比较慢。
      20.5.6 开发智能的事件处理程序
      20.5.7 javascript代码注意:谨慎使用with,避免使用eval Function函数,减少作用域链查找。
    20.6 图像优化
    20.6.1 优化图片大小
    20.6.2 通过CSS Sprites优化图片
    20.6.3 不要在HTML中使用缩放图片
    20.6.4 favicon.ico要小而且可缓存
  21.DNS解析过程
    21.1 先检查本地 hosts 文件中是否有映射,有则使用;
    21.2 查找本地 DNS 缓存,有则返回;
    21.3 根据配置在 TCP/IP 参数中设置 DNS 查询服务器,并向其进行查询,这里先称为本地 DNS;
    21.4 如果该服务器无法解析域名(没有缓存),且不需要转发,则会向根服务器请求;
    21.5 根服务器根据域名类型判断对应的顶级域名服务器(.com),返回给本地 DNS,然后重复该过程,直到找到该域名;
    备注:当然,如果设置了转发,本地 DNS 会将请求逐级转发,直到转发服务器返回或者也不能解析。
    结论:所以减少DNS的查询次数非常重要,页面加载时就尽量避免额外耗时。为了减少DNS的询次数,最好的解决方法就是在页面中减少不同的域名请求的机会。  
  22.JS新特性
    22.1 ES2015(ES6)(let、const关键字;箭头函数;class 类;模块(import/export);模板语法;函数参数默认值;rest参数;数组/对象 解构;Promise)
    22.2 ES2016(ES7) ES7在ES6的基础上主要扩展了一些数组的方法例如.includes(),还有指数运算符**
    22.3 ES2017(ES8) ES8添加了关键字async/await,让处理异步程序更加方便。我们能够通过使用它避免面条代码,提高异步代码的可读性.
    22.4 ES2018(ES9) ES9没有增加新的东西,但是增强了rest和扩展运算符。(const {enabled, ...others} = options;)(const param = {enabled: true, ...options})
    22.5 ES2019(ES10) ES10让使用try/catch更加简单,不需要声明一个Error然后去捕获他。这对不需要知道抛出的错误是什么的场景可能有些帮助。
    22.6 ES2020(ES11) 1.动态引入,减少包体积;2.BigInt;3.控制合并运算符??(取模);4.可选链?.。
  23.服务端渲染SSR
    23.1 定义:Server-Side Rendering ,简称SSR,意为服务端渲染
    23.2 解决的问题:(1.SEO,由于搜索引擎爬虫抓取工具可以直接查看完全渲染的页面;2.加速首屏加载,解决首屏白屏问题)
    23.3 如何实现:(1.手动搭建一个 SSR 框架;2.使用成熟的SSR 框架,如 Next.JS)
    23.4 Next.js重点:(1.通过server.get方法定义不同的渲染方式;2.用getInitialProps这个方法,可以兼顾服务端渲染和客户端渲染)
  24.React事件绑定原理
    24.1 实现:react并不是将click事件绑定到了div的真实DOM上,而是在document处监听了所有的事件,当事件发生并且冒泡到document处的时候,React将事件内容封装并交由真正的处理函数运行。
    24.2 优点:这样的方式不仅仅减少了内存的消耗,还能在组件挂载销毁时统一订阅和移除事件。
    24.3 冒泡到document上的事件也不是原生的浏览器事件,而是由react自己实现的合成事件。因此我们如果不想要是事件冒泡的话应该调用event.preventDefault().
  25.React数据渲染原理/React数据视图更新原理
    25.1 初始化数据state
    25.2 JSX模板
    25.3 数据+ 模板生成虚拟DOM(虚拟DOM就是一个JS对象,用它来描述真实的DOM)(损耗性能)
    25.4 用虚拟DOM的结构生成真实DOM来显示 
hello jsx
25.5 state 发生改变 25.6 数据 + 模板 生成新的虚拟DOM (极大提高性能) [‘div’ ,{ id:'abc },[‘span’,{},‘bye bye’]] 25.7 比较原始虚拟DOM和新的虚拟DOM的区别, 找到span内容 25.8 直接操作DOM该变span内容 避免频繁操作真实DOM极大提高性能, 26.单页面应用SPA与多页面应用MPA的区别和应用场景 26.1 单页面应用概念:将所有的活动局限于一个Web页面中,仅在该Web页面初始化时加载相应的HTML、JavaScript 和 CSS。利用JavaScript动态的变换HTML的内容,避免了页面的重新加载,流畅的用户体验。 26.2 单页面应用优势:(1.良好的交互体验,,页面显示流畅;2.良好的前后端工作分离模式,后端API通用化;3.减轻服务器压力,只用出数据就可以,不用管展示逻辑和页面合成) 26.3 单页面应用缺点及解决方案: 26.3.1 首屏加载慢。解决方案(1.Vue-router懒加载;2.使用CDN加速;3.异步加载组件;4.服务端渲染,还可以优化SEO) 26.3.2 不利于SEO。 解决方案(1.服务端渲染;2.页面预渲染;3.路由采用h5 history模式) 26.4 SPA和MPA应用场景:(1.SPA场景:DOM元素少;数据量多;SEO要求不高;2.MAP场景:DOM元素多;SEO要求高;大型应用) 27.import和require的区别(1.模块加载的时间。require:运行时加载,import:编译时加载(效率更高)2.模块的本质不同:require的模块就是对象,import则是export的代码;3.import自动使用严格模式) 28.vue-config.js如何使webpack生效: 28.1 configureWebpack(1.如果这个值是一个对象,则会通过 webpack-merge 合并到最终的配置中;2.如果你需要基于环境有条件地配置行为,或者想要直接修改配置,那就换成一个函数,该函数会在环境变量被设置之后懒执行) 28.2 chainWebpack(对内部的 webpack 配置(比如修改、增加Loader选项)(链式操作)) 29.webpack如何配置多入口: 29.1 entry: { home: './src/home', other: './src/other' } 29.2 plugins: [ new htmlWebpackPlugin({template: './index.html', filename: 'home.html', chunks: ['home']}), new htmlWebpackPlugin({template: './index.html', filename: 'other.html', chunks: ['other']})] 30.谈谈webpack 30.1 webpack的常见配置(1.entry 入口文件;2.output输出文件;3.module,loader设置;4.plugins设置,plugins:[ new HtmlWebpackPlugin({}) ])重新创建html文件 30.2 webpack的打包原理 (1.识别入口文件;2.通过逐层识别模块依赖;3.分析代码,转换代码,编译代码,输出代码;4.最终形成打包后的代码) 30.3 什么是loader(1.loader是文件加载器,能够加载资源文件,并对这些文件进行一些处理,诸如编译、压缩等,最终一起打包到指定的文件中;2.多个loader时,loader的执行顺序和配置中的顺序是相反的;) 30.4 什么是plugin(在webpack运行的生命周期中会广播出许多事件,plugin可以监听这些事件,在合适的时机通过webpack提供的API改变输出结果。) 30.5 loader和plugin的区别(1.loader,它是一个转换器;2.plugin是一个扩展器,针对是loader结束后,webpack打包的整个过程。它并不直接操作文件,而是基于事件机制工作,会监听webpack打包过程中的某些节点,执行广泛的任务) 30.6 plugin执行的顺序 30.6.1 webpack启动后,在读取配置的过程中会执行new MyPlugin(options)初始化一个MyPlugin获取其实例 30.6.2 在初始化compiler对象后,就会通过compiler.plugin(事件名称,回调函数)监听到webpack广播出来的事件 30.6.3 并且可以通过compiler对象去操作webpack
  31.eslint如何使用和配置
    31.1 安装:可以全局安装,也可以在项目下面安装。
    31.2 配置:配置方式有两种,但建议使用文件配置的形式,比较独立,便于维护。使用文件配置的方式:在项目的根目录下,新建一个名为 .eslintrc 的文件,在此文件中添加一些检查规则。
    31.3 错误等级:规则的错误等级有三种:(0或'off':关闭规则;1或'warn':打开规则,并且作为一个警告(并不会导致检查不通过);2或'error':打开规则,并且作为一个错误 (退出码为1,检查不通过)。)
    31.4 关闭eslint (第一种方法:根目录下有个文件  .eslintignore 文件,把你不需要校验的文件添加进去即可,如*.vue,*.js;2.第二种方法:项目根目录 ---> build ---> webpack.base.conf.js 注释掉如下的代码createlintingRule)
  32.hooks中useEffect
    32.1 第二个参数为一个空数组[]:获取数据只需要执行一次。
    32.2 第二个参数:使用一个数组指定副效应函数的依赖项,只有依赖项发生变化,才会重新渲染。不希望useEffect()每次渲染都执行,这时可以使用它的第二个参数。
    32.3 第一个参数是清理函数。在组件卸载时,执行该函数,清理副效应。如果不需要清理副效应,useEffect()就不用返回任何值。
    32.4 useEffect() 的注意点:如果有多个副效应,应该调用多个useEffect(),而不应该合并写在一起。
  33.react哪些生命周期函数被废弃
    33.1 React16.3版本废弃了原有的componentWillMount()、componentWillUpdate()以及componentWillReceiveProps(),
    33.2 废除原因:被废弃的三个函数都是在render之前,因为fiber的出现,很可能因为高优先级任务的出现而打断现有任务导致它们会被执行多次
    33.3 新增的两个生命周期
      33.3.1 getDerivedStateFromProps,取代以前的函数componentWillReceiveProps。是一个纯函数,论是Mounting还是Updating,也无论是因为什么引起的Updating,全部都会被调用。只执行一次。
      33.3.2 getSnapshotBeforeUpdate,render之后,更新dom之前,state已更新。可以用来读取dom,强制用户只能在mount阶段读取dom.在Fiber架构中只会调用一次,实现了类似willMount的效果。
  34.前端去重方案
    34.1 ES6的set()方法。var arr=[1,5,5,5,2,1,4,2]; arr=[...new Set(arr)];
    34.2 使用遍历+indexOf()。
    34.3 利用obj的特质:key一样值不一样,后面覆盖前面,key,value都一样,会去掉重复的。具体实现:先把每个value赋值为0,然后Object.keys(obj)
    34.4 使用 includes。在for循环里,if(!arrNew.includes(arr[i])){ arrNew.push(item) }
    34.5 filter+indexOf。没有重复的数组元素索引值(index)与首次出现的索引位置(indexOf)相同。arr.filter((item,index)=>{ return arr.indexOf(item) == index; })
  35.合并两个对象的方法
    35.1 $.extend()。其中$.extend(obj1, obj2),会改变obj1的值;$.extend({}, obj1, obj2)则不会改变obj1的值。
    35.2 遍历赋值。用for in 加 hasOwnProperty判断自有属性 for(var key in obj2){ if(obj2.hasOwnProperty(key)===true){ obj1[key]=obj2[key]; }}
    35.3 Object.assign()。Object.assign(o1, o2, o3),会改变o1的值;Object.assign({}, o1, o2, o3),不会改变o1的值。
  36.深拷贝与浅拷贝
    36.1 浅拷贝:当一个对象拷贝另一个对象的数据的时候,只要一个对象的数据发生改变另一个对象的数据也会发生改变。因为浅拷贝拷贝的是引用的地址。
    36.2 浅拷贝实现:
      36.2.1 ES6的方法:Object.assign({},obj)  作用:将第二个参数及以后的参数合并到第一个对象里。 
      36.2.2 使用 for in 循环,遍历每一个属性,将他们赋值给新的对象。要求对象必须是多层的状态下才能实现浅拷贝
      36.2.3 $.extend()。$.extend({},obj,obj1) 如果填true的情况下是深考贝 什么也不写就是浅拷贝
    36.3 深拷贝:当一个对象拷贝另一个对象的数据的时候,其中一个对象的数据发生变化不会影响另一个对象的数据。因为深考贝拷贝的是对象的数据而不是地址
    36.4 深拷贝实现:
      36.4.1 对象是单层的情况下Object.assign({},obj);
      36.4.2 差不多比较完美 $.extend(true,{},obj,obj1);
      36.4.3 JSON.parse、JSON.stringfiy 不能拷贝函数,但用在拷贝数据库数据时,不影响。因为数据库没有函数。所以推荐使用。其原理是:先将对象转换为字符串、再转换成对象,此时地址一定发生了变化,所以可以实现浅拷贝。
  37.nextTick实现原理
    37.1 理解:Vue.nextTick(()=>{})它可以在DOM更新完毕之后执行一个回调
    37.2 原理:(1.vue用异步队列的方式来控制DOM更新和nextTick回调先后执行;2.microtask因为其高 优先级特性,能确保队列中的微任务在一次事件循环前被执行完毕;3.因为兼容性问题,vue不得不做了microtask向macrotask的降级方案)
    37.3 场景:(1.created()里使用this.$nextTick()可以等待dom生成以后再来获取dom对象;2.mounted中this.$nextTick()获取到的值为dom更新之后的值)
38.谈谈watch和computed
  38.1 区别
    38.1.1 watch中的函数是不需要调用的;computed内部的函数调用的时候不需要加()
    38.1.2 watch 属性监听,监听属性的变化;computed:计算属性通过属性计算而得来的属性
    38.1.3 watch需要在数据变化时执行异步或开销较大的操作时使用;computed则是对于任何复杂逻辑或一个数据属性在它所依赖的属性发生变化时,也要发生变化的情况下使用。
    38.1.4 watch 一个对象,键是需要观察的表达式,值是对应回调函数。主要用来监听某些特定数据的变化,从而进行某些具体的业务逻辑操作;
           computed 属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算;函数必须用return返回最终的结果;没有发生改变的时候,那么调用当前函数的时候结果会从缓存中读取
  38.2 使用场景
    38.2.1 watch当一条数据影响多条数据的时候就需要用,比如搜索数据。
    38.2.2 当一个属性受多个属性影响的时候就需要用到computed, 比如购物车商品结算的时候。
39.微前端实现 阿里框架QIANKUN
  39.1 QIANKUN都做了什么?
    39.1.1 实现 loadApp 函数,是最关键、重要的一步
      39.1.1.1 解析 html,获取 JavaScript, CSS, HTML,用import-html-entry 
      39.1.1.2 创建容器 container,同时加上 css 样式隔离,主要有 Shadow DOM 和 Scoped CSS 两种方案
      39.1.1.3 创建沙箱,JS隔离。监听 window 的变化,并对一些函数打上补丁
      39.1.1.4 提供更多的生命周期,在 beforeXXX 里注入一些 qiankun 提供的变量
      39.1.1.5 返回带有 bootstrap, mount, unmount 属性的对象
    39.1.2 提供预加载,提前下载 HTML、CSS、JS,并有三种策略(1.全部立马预加载;2.全部在第一个加载后预加载;3.一些立马预加载,一些在第一个加载后预加载)
    39.1.3 提供全局状态管理,类似 Redux,Event Bus
    39.1.4 提供全局错误处理,主要监听 error 和 unhandledrejection 两个事件
  39.2 QIANKUN不足:(1.没有对 localStorage 进行隔离;2. cookie, indexedDB 的共享等;3.如果单个页面下多个子应用都依赖了前端路由怎么办呢)
  40.Vue路由守卫
    40.1 全局路由守卫( router.beforeEach;router.afterEach)
    40.2 组件内的守卫(beforeRouteEnter:(to,from,next)=>{};beforeRouteLeave:(to,from,next)=>{};beforeRouteUpdate:(to,from,next)=>{})
    40.3 路由独享的守卫(beforeEnter:(to,from,next)=>{})
  41.Vue与React区别与选择
    41.1 监听数据变化的实现原理不同(1.Vue通过 getter/setter以及一些函数的劫持,能精确知道数据变化;2.React默认是通过比较引用的方式(diff)进行的,如果不优化可能导致大量不必要的VDOM的重新渲染。)
    41.2 组合不同功能的方式不同(1.Vue组合不同功能的方式是通过mixin;2.React组合不同功能的方式是通过HoC(高阶组件),本质是高阶函数)
    41.3 组件通信的区别(1.vue通过props,子组件事件,provide和inject结合等进行组件通信;2.React通过props向子组件传递,通过context实现跨层级通信。)
    41.4 模板渲染方式的不同 (Vue是通过一种拓展的HTML语法进行渲染;React是通过JSX渲染模板,通过JS语法实现的,更加纯粹更加原生)
    41.5 渲染过程不同(Vue在渲染过程中,会跟踪每一个组件的依赖关系,不需要重新渲染整个组件树;React在应用的状态被改变时,全部子组件都会重新渲染)
    41.6  Vuex和Redux的区别(1.在Vuex中,$store被直接注入到了组件实例中,因此可以比较灵活的使用:使用dispatch、commit提交更新,通过mapState或者直接通过this.$store来读取数据;2.在Redux中,我们每一个组件都需要显示的用connect把需要的props和dispatch连接起来。)
  42.Webpack常用配置
    42.1 webpack是目前前端开发中最流行的打包工具,不仅能实现 JS 打包,还能将 CSS 文件,图片文件,甚至是 LESS 文件打包,每一个文件都是一个独立的模块,并且实现按需加载。使用时需要安装 webpack 、 webpack-cli 、webpack-dev-server三个基础模块。
    42.2 源码
      module.exports = {
        entry: './src/index.js',
        output:{
            filename:'bundle.js',
            path:path.resolve(__dirname,'dist')
        },
        module:{
            rules:[
                  {
                    test: /\.js$/,
                    loader: 'babel-loader?cacheDirectory=true',
                    include: [
                      resolve('src'),
                    ],
                    exclude:path.resolve(__dirname, 'node_modules')
                  },
                {
                    test:/\.css$/,
                    use:[
                        'style-loader',
                        'css-loader',
                        'postcss-loader'

                    ]
                },{
                    test:/\.(png|svg|jpg|gif)$/,
                    loader: 'url-loader',
                    options: {
                      limit: 10000,
                      name: utils.assetsPath('img/[name].[hash:7].[ext]')
                    }
                }
            ]
        }
      }
    42.3 配置参数说明
      mode:两种 mode 模式可供选择,一种是开发环境,命令为 webpack --mode = development,打包出来的文件未经过压缩;一种是生产环境,命令是 webpack --mode = production ,打包出来的文件是经过压缩的。
      entry:资源入口文件,所有的资源最后会打包成一个 JS 文件。
      output:打包之后存放的文件路径。path 为相对路径,filename 为打包后的文件名。
      module:rules 配置编译规则,test 正则匹配,exclude 排除特定条件,use-loader,test 匹配到的解析器模块,use-options,与use-loader配合使用。
      plugins:插件。plugins 与 loader 的区别在于,loader 只是一个解析模块,比如将 ES5 解析成 ES6,LESS 文件解析成 CSS 文件,为了兼容浏览器。而 plugins 是将 loader 之后的文件进行优化分类、压缩、提供公共代码等。
      devServer:服务器配置,contentBase 文件路径,compress 是否启动 gzip 压缩,host 主机地址,port 端口号,publicPath。
    42.4 常用 plugins
      1. extract-text-webpack-plugin 与 mini-css-extract-plugin  分离 .css 分解,后者需要 webpack 4.2.0 版本以上。
      2. UglifyJsPlugin 压缩 js 文件,减小 js 文件。
      3. html-webpack-plugin 与 html-loader 生成 html 文件。
      4. clean-webpack-plugin 每次构建之前清理历史打包文件。
  43.Css3新增特性
    43.1 CSS3选择器(.class,#id,*,element,:link,:visited,:active,:hover,:before,:after,:first-child...)
    43.2 CSS3 边框(Borders) 用CSS3,你可以创建圆角边框,添加阴影框,并作为边界的形象而不使用设计程序.border-image; border-radius; box-shadow.
    43.3 CSS3 背景 background-clip	规定背景的绘制区域。background-origin规定背景图片的定位区域。background-size规定背景图片的尺寸。
    43.4 CSS3 渐变 CSS3 定义了两种类型的渐变(gradients):线性渐变(Linear Gradients)- 向下/向上/向左/向右/对角方向; 径向渐变(Radial Gradients)- 由它们的中心定义
    43.5 CSS3 文本效果 text-overflow规定当文本溢出包含元素时发生的事情。text-shadow	向文本添加阴影。ext-wrap规定文本的换行规则。
    43.6 CSS3 字体 您所选择的字体在新的CSS3版本有关于@font-face规则描述
    43.7 CSS3 转换和变形 transform	适用于2D或3D转换的元素; translate(x,y)	定义 2D 转换,沿着 X 和 Y 轴移动元素。translate3d(x,y,z)定义 3D 转化。
    43.8 CSS3 过渡 transition
    43.9 CSS3 动画 要创建CSS3动画,你需要了解@keyframes规则。@keyframes规则是创建动画
    43.10 CSS3 多列
    43.11 CSS3 多媒体查询 @media all and(min-width:800px){...} @media all 是媒体类型,也就是说,将此 CSS 应用于所有媒体类型。(min-width:800px) 是包含媒体查询的表达式,如果浏览器的最小宽度为 800 像素,则会告诉浏览器只运用下列 CSS。
  44.终端代码重复率检测
    44.1 在技术上,重复代码检测主要有以下分类:
      基于代码行的
      基于标识符(token)的
      基于度量(metrics)的
      基于抽象语法树(Abstract Syntax Tree)的
      基于程序依赖图(Program Dependence Graph)的
    44.2 由于前端源代码文件格式多样,重复率检测除了源码检测以外,还可以从检测打包文件和文件退化角度考虑。
    44.3 检测前端代码重复率的工具有jsinspect、jscpd,PMD-CPD(PMD's Copy/Paste Detector)中也支持js文件的重复率检测。
      44.3.1 jsinspect工具支持js和jsx格式的文件,基于抽象语法树,可以检测出结构类似的代码块
      44.3.2 jscpd工具支持文件格式广泛,如java、oc、js、jsx、vue、ts、less等。其重复率判定依据为一定长度标识符的MD5值是否相同
      44.3.3 PMD-CPD工具支持js文件检测,也可以自己开发扩展包来解析指定的语言:官方介绍
  45.前端代码质量优化
    45.1 项目角度:统一框架 - 统一技术手段。推荐每个项目在开始的时候自己抽分UI组件库,建立一个公司的私有npm库,然后大家所做的项目中的组件,都能沉淀下来,建立自己的npm库,其中不光可以有UI组件、还可以有业务组件、脚手架等。
    45.2 格式角度:(1.eslint(lint: 包扎伤口的纱布);2.stylelint 跟eslint 一样,只不过是对于css的一系列规范。)
    45.3 代码角度:
      45.3.1 变量命名,驼峰命名法 我应该不用多说了,这个是最最最基本的命名规范。
      45.3.2 组件不超过250行;
      45.3.3 全局样式污染问题优化,推荐classnames插件,拼接业务唯一标识到className前面,这样比直接用hash更好调试,并且每个组件就算格式一样 className 起名字一样也不会混淆。
      45.3.4 渲染次数优化,问题的解决方法在于合理触发render。
      45.3.5 数据抽象-逻辑解耦
      45.3.6 接口返回statusCode异常,用try...catch接收。我们可以把这个抓取js错误的方法放在入口处,没错,就是路由。单页面应用的项目都是把路由插入到单页面节点中,在插入的方法外层try catch,一劳永逸。 
      45.3.7  所有节点需有唯一识别key
      45.3.8  prettier格式化代码
    45.4 Git角度(1.通过git precommit钩子,每个人在上传代码的时候做一层拦截,保证上传到gitlab上的代码质量。2.锁定master分支,其余代码想合并到master 的时候,需要提交merge request,然后需要进行代码评审,至少两个人)
  46.防抖与节流的区别与实现
    46.1 区别:防抖是将多次执行变为最后一次执行,节流是将多次执行变为每隔一段时间执行
    46.2 防抖实现
      function debounce(fn, wait) {
          var timeout = null;      //定义一个定时器
          return function() {
              if(timeout !== null) 
                  clearTimeout(timeout);  //清除这个定时器
              timeout = setTimeout(fn, wait);  
          }
      }
      // 处理函数
      function handle() {
          console.log(Math.random()); 
      }
      // 滚动事件
      window.addEventListener('scroll', debounce(handle, 1000));
      当持续触发scroll函数,handle函数只会在1秒时间内执行一次,在滚动过程中并没有持续执行,有效减少了性能的损耗
    46.3 节流实现(时间戳和定时器)
      单用时间戳或者定时器都有缺陷,我们更希望第一次触发马上执行函数,最后一次触发也可以执行一次事件处理函数
      var throttle = function(func, delay) {
        var timer = null;
        var startTime = Date.now();  //设置开始时间
        return function() {
          var curTime = Date.now();
          var remaining = delay - (curTime - startTime);  //剩余时间
          var context = this;
          var args = arguments;
          clearTimeout(timer);
          if (remaining <= 0) {      // 第一次触发立即执行
            func.apply(context, args);
            startTime = Date.now();
          } else {
            timer = setTimeout(func, remaining);   //取消当前计数器并计算新的remaining
          }
        }
      }
      function handle() {
        console.log(Math.random());
      }
      window.addEventListener('scroll', throttle(handle, 1000));
  47.垃圾回收机制
    47.1 定义:垃圾回收(Garbage Collection,GC),顾名思义就是释放垃圾占用的空间,防止内存泄露。有效的使用可以使用的内存,对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收。
    47.2 垃圾判断算法 (1。标记-清除算法;2. 复制算法 3.标记-整理算法;4.分代收集算法)
  48.v-model语法糖(相当于)
  49.promise常用API
    49.1 定义: Promise是异步编程的一种解决方案.Promise是一个许诺、承诺,是对未来事情的承诺,承诺不一定能完成,但是无论是否能完成都会有一个结果。
    49.2 理解:Pending  正在做。。。;Resolved 完成这个承诺;Rejected 这个承诺没有完成,失败了;Promise 用来预定一个不一定能完成的任务,要么成功,要么失败。
    49.3 特点:()对象的状态不受外界影响;一旦状态改变,就不会再变,任何时候都可以得到这个结果)
    49.4 基本的API(1.new Promise;2.PromiseObj.then(resolveFn,rejectFn);3.Promise.all()等待所有的 异步任务执行结束了,才返回;4.PromiseObj.catch()出错信息;5.PromiseObj.resolve()将一个值,数字,字符串...转换为Promise对象)
  50.keep-alive用法(keep-alive是vue内置的一个组件,而这个组件的作用就是能够缓存不活动的组件。在keep-alive上有两个属性:include 值为字符串或者正则表达式匹配的组件name会被缓存。exclude 值为字符串或正则表达式匹配的组件name不会被缓存。)
 
      51.对象遍历方法
    51.1 for in
    51.2 Object.keys(obj);Object.values(obj)返回值:一个表示给定对象的所有可枚举属性的字符串数组
    51.3 使用Object.getOwnPropertyNames(obj) 返回一个数组,包含对象自身的所有属性(包含不可枚举属性)遍历可以获取key和value
    51.4 forEach循环 遍历数组中的每一项,没有返回值,对原数组没有影响,不支持IE
    51.5 用.each的方式进行循环,.each的方式进行循环,.each()可以遍历数组和对象
    51.6 some()是对数组中每一项运行指定函数,如果该函数对任一项返回true,则返回true。
    51.7 every()是对数组中的每一项运行给定函数,如果该函数对每一项返回true,则返回true。
    51.8 filter()遍历不会改变原始数组,返回新数组
    51.9 for  of遍历,可以正确响应break、continue和return语句
    51.10 map循环,有返回值,可以return出来.ap的回调函数中支持return返回值;return的是啥,相当于把数组中的这一项变为啥(并不影响原来的数组,只是相当于把原数组克隆一份,把克隆的这一份的数组中的对应项改变了);
    51.11 find,返回一个符合条件的数组的第一个元素
    51.12 使用Reflect.ownKeys(obj)遍历,返回一个数组,包含对象自身的所有属性,不管属性名是Symbol或字符串,也不管是否可枚举. 
  52.vue-cli3常用配置 (项目的根目录下创建vue.config.js文件)
    参考搭建整个项目:https://www.cnblogs.com/zhigu/p/12009618.html
    module.exports = {
      // 基本路径
      publicPath: '/',//注意新版本这里改成了publicpath
      // 输出文件目录
      outputDir: 'dist',
      // eslint-loader 是否在保存的时候检查
      lintOnSave: true,
      // use the full build with in-browser compiler?
      // https://vuejs.org/v2/guide/installation.html#Runtime-Compiler-vs-Runtime-only
      runtimeCompiler: false,
      // webpack配置
      // see https://github.com/vuejs/vue-cli/blob/dev/docs/webpack.md
      chainWebpack: () => {},
      configureWebpack: () => {},
      // vue-loader 配置项
      // https://vue-loader.vuejs.org/en/options.html
      // vueLoader: {},
      // 生产环境是否生成 sourceMap 文件
      productionSourceMap: true,
      // css相关配置
      css: {
        // 是否使用css分离插件 ExtractTextPlugin
        extract: true,
        // 开启 CSS source maps?
        sourceMap: false,
        // css预设器配置项
        loaderOptions: {},
        // 启用 CSS modules for all css / pre-processor files.
        modules: false
      },
      // use thread-loader for babel & TS in production build
      // enabled by default if the machine has more than 1 cores
      parallel: require('os').cpus().length > 1,
      // 是否启用dll
      // See https://github.com/vuejs/vue-cli/blob/dev/docs/cli-service.md#dll-mode
      // dll: false,
      // PWA 插件相关配置
      // see https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-pwa
      pwa: {},
      // webpack-dev-server 相关配置
      devServer: {
          open: true,//编译项目浏览器自动打开
          https: false,//是否启动https访问
          port: 9909,//本地访问端口号
          disableHostCheck: true ,//允许外部访问本地服务
          proxy: {
            "/": {
                target: "http://118.25.82.97:3000/",//需要被代理服务器(后端服务器)
                changeOrigin: true,
                pathRewiter: {
                    "^/": "/"
                }
            },
      },
      before: app => {}
      },
      // 第三方插件配置
      pluginOptions: {
      // ...
      }
    }
  53.编程式路由
    53.1 定义:通过js来实现页面的跳转
    53.2 具体实现(1.$router.push("name");2.$router.push({path:"name"});3.$router.push({path:"name?a=123"})或者$router.push({path:"name",query:{a:123}});4.$router.go(1))
  54.前后端分离架构落地
    54.1 技术方案有四种:前端模板(Ajax + 字符串模板)、MVVM(Vue、React)、Node模板(Express + ejs)、SSR(Node + Vue SSR)。这其中最古老的方案就是Ajax + 字符串模板,它本质上是拼接字符串。
    54.2 浏览器兼容:无论是服务器渲染还是平常的渲染方式都支持IE6+,使用SSR或Node做渲染在浏览器兼容方面则会比较弱。基于现代MVVM框架的技术方案,同样也处于劣势,在浏览器兼容要求较高的场合中,无法使用。
    54.3 SEO支持:对于SEO有要求的网页来说,使用web模板和Vue方案,不太合适。相对来说web模板要好一点,可以在页面未渲染之前添加一些介绍之类。Node和SSR在SEO方面问题不大,它们都是服务端渲染,首屏都包含足够多的数据。
    54.4 首屏渲染耗时:现在的各种技术方案中对于首屏渲染耗时,显然使用Node是最快的。毕竟它是服务端渲染,数据是由Node服务端向服务提供方获取的。SSR渲染的花费时间相对于Node会多30%-50%。Web模板和Vue都是读取数据然后加载,其中Vue的渲染耗时会更久一些。总体来看在首屏渲染耗时方面MVVM框架是最慢的。
    54.5 异步接口速度:在首屏加载完成后,很多页面都会有懒加载,需要向服务端请求相应的数据接口。这方面MVVM框架和web模板是直连后端的,而Node和SSR的方案都使用Nodejs做中间层转发一次,消耗掉一部分的网络连接,多出来的是Node服务器到服务提供方的服务。
    54.5 高可用:Web模板毫无疑问在高可用方面是做的最好的,只要后台服务提供方没有挂,一般来说Web模板不会出太多问题。MVVM情况会复杂一些,在浏览器兼容上要求更高,测验量也会更多,但总归有些地方会测试不到。
        Node作为中间平台,不仅要关心前端CDN还要注意Node服务器会不会出现问题,这样每多一个环节在高可用方面的就会差上一些。而SSR不仅要在Node上有高可用的要求,如果还引入了前后端代码同构,同构代码就有可能会在Node上出现各种问题。基于这种情况我们认为SSR在高可用方面是最差的。
  55.前端内存泄漏及处理办法
    55.1 定义:系统进程不再用到的内存,没有及时释放,就叫做内存泄漏(memory leak)。当内存占用越来越高,轻则影响系统性能,重则导致进程崩溃。Chrome 限制了浏览器所能使用的内存极限(64 位为 1.4GB,32 位为 1.0GB)
    55.2 引起内存泄漏的原因
      55.2.1 意外的全局变量(未声明变量;使用 this 创建的变量(this 的指向是 window)。)解决方法:(避免创建全局变量;使用严格模式,在 JavaScript 文件头部或者函数的顶部加上 use strict。)
      55.2.2 闭包引起的内存泄漏 (如果在使用结束后没有将局部变量清除,就可能导致内存泄露。)解决:将事件处理函数定义在外部,解除闭包,或者在定义事件处理函数的外部函数中。
      55.2.3 没有清理的 DOM 元素引用 (原因:虽然别的地方删除了,但是对象中还存在对 dom 的引用)解决方法:手动删除,elements.btn = null。
      55.2.4 被遗忘的定时器或者回调 (定时器中有 dom 的引用,即使 dom 删除了,但是定时器还在,所以内存中还是有这个 dom。)解决方法:(1.手动删除定时器和 dom。2.removeEventListener 移除事件监听)
    55.3 vue 中容易出现内存泄露的几种情况
      55.3.1 声明的全局变量在切换页面的时候没有清空。解决方案:在页面卸载的时候顺便处理掉该引用。destroyed () { window.test = null // 页面卸载的时候解除引用 }
      55.3.2 监听在 window/body 等事件没有解绑.解决方法:在页面销毁的时候,顺便解除引用,释放内存。beforeDestroy () {window.removeEventListener('resize', this.func)}
      55.3.3 绑在 EventBus 的事件没有解绑.解决方法:在页面卸载的时候也可以考虑解除引用。destroyed () { this.$EventBus.$off() }
      55.3.4 Echarts,页面切换后,echarts 图例是销毁了,但是这个 echarts 的实例还在内存当中。解决方法:加一个 beforeDestroy()方法释放该页面的 chart 资源,beforeDestroy () {this.chart.clear()}
      55.3.5 v-if 指令产生的内存泄露:v-if 绑定到 false 的值,但是实际上 dom 元素在隐藏的时候没有被真实的释放掉。解决办法:使用 Choices API 中的 destroy() 方法将其清除
      55.3.6 ES6 防止内存泄漏.由于监听函数是放在 WeakMap 里面,一旦 dom 对象 ele 消失,与它绑定的监听函数 handler 也会自动消失。
        const listener = new WeakMap()
        listener.set(ele, handler)
        ele.addEventListener('click', listener.get(ele), false)
  56.promise的三种状态(Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败),只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态,这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。)
  57.set和map的区别
    57.1 Map是键值对,Set是值的集合,当然键和值可以是任何的值;
    57.2 Map可以通过get方法获取值,而set不能因为它只有值;
    57.3 都能通过迭代器进行for...of遍历;
    57.4 Set的值是唯一的可以做数组去重,Map由于没有格式限制,可以做数据存储
    57.5 map和set都是stl中的关联容器,map以键值对的形式存储,key=value组成pair,是一组映射关系。set只有值,可以认为只有一个数据,并且set中元素不可以重复且自动排序
  58.beforeCreate和created的区别(1.beforeCreate,实例尚未被初始化,data observer和 event/watcher也还未被调用,2.实例已经被初始化,但是还没有挂载至$el上,所以我们无法获取到对应的节点,但是此时我们是可以获取到vue中data与methods中的数据的)
  59.前端安全
    59.1 跨站脚本攻击(XSS)
      59.1.1 定义:XSS 攻击是指攻击者在网站上注入恶意的客户端代码,利用恶意脚本对客户端网页进行篡改,从而在用户浏览网页时,对用户浏览器进行控制或者获取用户隐私数据的一种攻击方式。
      59.1.2 攻击方式(1.反射型XSS,恶意代码并没有保存在目标网站,通过引诱用户点击一个链接到目标网站的恶意链接来实施攻击。2.存储型XSS,恶意代码被保存到目标网站的服务器中,这种攻击具有较强的稳定性和持久性,比较常见场景是在博客,论坛、OA、CRM等社交网站上。3.DOM Based XSS。基于DOM的XSS攻击是指通过恶意脚本修改页面的DOM结构,是纯粹发生在客户端的攻击。)
      59.1.3 防范手段 (1.输入检查。移除用户上传的节点,