首页IT科技2021年前端面试(2023年前端面试题汇总)

2021年前端面试(2023年前端面试题汇总)

时间2025-05-05 14:54:40分类IT科技浏览3747
导读:一:JavaScript 1、闭包是什么?利弊?如何解决弊端?...

一:JavaScript 

1           、闭包是什么?利弊?如何解决弊端?

闭包是什么:JS中内层函数可以访问外层函数的变量           ,外层函数无法操作内存函数的变量的特性          。我们把这个特性称作闭包                 。

闭包的好处

隔离作用域              ,保护私有变量;有了闭包才有局部变量      ,要不然都是全局变量了    。 让我们可以使用回调         ,操作其他函数内部; 变量长期驻扎在内存中              ,不会被内存回收机制回收         ,即延长变量的生命周期;

闭包的弊端:内层函数引用外层函数变量      ,内层函数占用内存       。如果不释放内存              ,过多时           ,易引起内存泄露                  。

解决办法:无法自动销户   ,就及时手动回收               ,使用后将函数的引用赋null       。

2              、深度拷贝

1      、深拷贝与浅拷贝的区别?

拷贝的层级不同             ,深拷贝是指每一层数据的改动都不会影响原对象和新对象,浅拷贝只有第一层的属性变动不互相影响             ,深层的数据变动还会互相影响    。

浅拷贝:Object.assign 深拷贝:JSON.stringify和JSON.parse

2         、JSON的stringify和parse处理的缺点?

如果对象中有属性是function或者undefined               ,处理后会被过滤掉; 如果属性值是对象   ,且由构造函数生成的实例对象           ,会丢弃对象的constructor;

3              、$.extend()

使用jquey的extend方法不仅能实现深度拷贝              ,还能实现深度合并                 。具体用法

深度拷贝:$.extend({},targetObject) // targetObject是需要复制的对象

深度合并:$.extend(true,{},targetObject1,targetObject2) // 可以将两个对象深度合并后再返回出一个新对象

3         、如何判断空对象?如何区分数据类型?

    判断空对象

1      、用JSON的stringify和parse转成字符串后      ,跟{}对比; 2              、用ES6         ,判断Object.keys(targetObject)返回值数组的长度是否为0; 3           、用ES5              ,判断Object.getOwnPropertyNames(targetObject)返回的数组长度是否为0;

   区分数据类型

let a = [1,2] Object.prototype.toString.call(a) // [object Array]

4   、如何改变this指向?区别?

call/apply let a = { name: sunq, fn:function(action){ console.log(this.name + love + action); } } let b = {name:sunLi} // 正常的this指向 a.fn(basketball); // sunq love basketball // 改变this指向         ,并体现call与apply的区别 a.fn.apply(b,[football]); // sunLi love football a.fn.call(b,football); // sunLi love football // call 和 apply 区别: call 和 apply 都是可以改变this 指向的问题, call 方法中传递参数要求一 // 个 一个传递参数          。 但是apply 方法要求传递参数是一个数组形式  。 bind // 还是上面的示例      ,bind也可以实现call和apply的效果                。 // bind的不同之处在于bind会返回一个新的函数             。如果需要传参              ,需要再调用该函数并传参 a.fn.bind(b)(piano); // sunLi love piano

5               、沙箱隔离怎么做?

使用iframe可以实现           ,变量隔离

6             、浏览器存储   ,他们的区别?

localStorage:永久保存               ,以键值对保存             ,存储空间5M sessionStorage:关闭页签/浏览器时清空 cookie:随着请求发送,通过设置过期时间删除 session:保存在服务端

localStorage/sessionStorage是window的属性             ,cookie是document的方法

7、常用的数组方法有哪些?

改变原数组:push             、pop               、shift   、unshift           、sort              、splice      、reverse 不改变原属组:concat         、join              、map         、forEach      、filter              、slice

    slice和splice的区别?

slice切片的意思               ,根据传入的起始和终止下标   ,获取该范围数组。 splice可根据传入参数个数不同实现删除           、插入操作           ,直接操作原数组             。第1个参数为起始下标              ,第2个为删除个数      ,第3个为要增加的数据                。

数组如何滤重?

8   、Dom事件流的顺序?什么是事件委托?

当页面上的一个元素被点击时         ,先从document向下一层层捕获到该元素  。然后再向上冒泡              ,一层层触发          。

事件委托是将事件写在父级元素上         ,e.target是事件捕获时那个最小的元素      ,即选中的元素                 。所以可以根据e.target操作选中的元素    。这样不需要给每个子元素绑定事件              ,代码更加简约       。

9               、对原型链的认识?

js通过原型链模拟实现面向对象           ,比如通过实例化一个构造函数可以给每个对象挂载自己专属的属性   ,通过给类的prototype上赋方法是所有对象所共有的方法                  。每次实例化不再赋值原型链上的方法       。

10             、防抖/节流的区别?

区别:防抖只会在最后一次事件后执行触发函数               ,节流不管事件多么的频繁             ,都会保证在规定时间段内触发事件函数    。

防抖:

原理是维护一个定时器,将很多个相同的操作合并成一个                 。规定在delay后触发函数             ,如果在此之前触发函数               ,则取消之前的计时重新计时   ,只有最后一次操作能被触发          。例如:实时搜索的input           ,一直输入就不发送  。

let input = document.querySelector("input"); let time = null;//time用来控制事件的触发 input.addEventListener(input,function(){ //防抖语句              ,把以前的定时删除      ,只执行最后一次 if(time !== null){ clearTimeout(time); } time = setTimeout(() => { console.log(this.value);//业务实现语句         ,这里的this指向的是input },500) }) 节流:

原理是判断是否达到一定的时间来触发事件                。某个时间段内只能触发一次函数             。例如:在指定的时间内多次触发无效

//节流 function throttle(fn, time) {//连续触发事件 规定的时间 let flag = false; return function () { //使用标识判断是否在规定的时间内重复触发了函数              ,没有就触发         ,有就不触发 if (!flag) {//不为假时 执行以下 fn();//触发事件 flag = true;//为真 setTimeout(() => {//超时调用(在规定的时间内只执行一次) flag = false; }, time); } } } mybtn.onclick = throttle(btn, 3000);//单击事件 节流(btn,3s时间)

二:Html

1、重绘和重排(回流/重构/重载)是什么?如何优化?

样式的调整会引起重绘      ,比如字体颜色             、背景色调整等 Dom的变动会引起重排              ,比如定位改动               、元素宽高调整

避免循环插入dom           ,比如table的行。可以js循环生成多个dom后   ,一次性插入             。

2   、html5有哪些新特性?

本地存储               ,比如localStorage           、sessionStorage 语义化标签             ,如header              、footer      、nav等,使代码结构清晰             ,利于seo canvas svg web worker               ,在主线程外再创建一个线程   ,可与主线程交互 拖放功能

三:CSS

1         、如何实现一个宽度不固定的上下左右居中的弹框?

方法一: .pop{ width: 300px; height: 300px; position: fixed; left: 0; right: 0; top: 0; bottom: 0; margin: auto; border: 1px solid red; } 方法二: .chartLengend { // 父元素 width: 60px; height: 40px; position: relative; .line { // 子元素 width: 100%; height: 3px; background-color: #DEA182; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); border-radius: 2px; } }

2              、伪类和伪元素区别?

伪类本质上用于弥补常规css选择器的不足           ,因为如果没有我们可能需要多写一个class              ,所以叫伪类 .class:last-child{} .class:first-child{} a:link {color:green;} a:visited {color:green;} a:hover {color:red;} a:active {color:yellow;} 伪元素本质上是创建了一个有内容的虚拟元素      ,如::before   ::after                。因为相当于多了一个元素/节点         ,所以叫为元素 // :before用于在某个元素之前插入某些内容  。 // :after用于在某个元素之后插入某些内容          。 css p:before{ content:"Read this: "; } html: <p>I live in Ducksburg</p> 页面展示: Read this: I live in Ducksburg F12看dom中: before Read this: I live in Ducksburg

四:Vue

1         、单页面应用是什么?优缺点?如何弥补缺点

单页面对一个入口DOM通过路由去更改内容              ,整个应用只有一个html页面

SPA优点:用户体验好         ,没有页面切换就没有白屏情况;

SPA缺点:首屏加载慢      ,不利于SEO

SPA弥补:通过压缩      、路由懒加载缓解首屏慢;通过SSR 服务器端渲染解决SEO问题;

2              、组件及通信方式有哪些?

2.1           、什么是组件?

组件是可复用的 Vue 实例              ,且带有一个名字:在这个例子中是                  。我们可以在一个通过 new Vue 创建的 Vue 根实例中           ,把这个组件作为自定义元素来使用:

声明组件

// 定义一个名为 button-counter 的新组件 Vue.component(button-counter, { data: function () { return { count: 0 } }, template: <button v-on:click="count++">You clicked me {{ count }} times.</button> })

使用组件(把组件当作自定义元素)

<div id="components-demo"> <button-counter></button-counter> </div>

引入组件

new Vue({ el: #components-demo })

2.2   、父向子传值

Prop 是你可以在组件上注册的一些自定义 attribute    。当一个值传递给一个 prop attribute 的时候   ,它就变成了那个组件实例的一个 property       。为了给博文组件传递一个标题               ,我们可以用一个 props 选项将其包含在该组件可接受的 prop 列表中:

组件内部声明prop

Vue.component(blog-post, { props: [title], template: <h3>{{ title }}</h3> })

父组件里调用             ,并给prop赋值,传递到组件内部

<blog-post title="My journey with Vue"></blog-post>

2.3               、父组件监听子组件事件

其实就是通过在父组件声明方法             ,并绑定在子组件上                  。以子组件内部触发方法的形式               ,向父组件传参   ,实现子向父传值的效果       。如下

父组件中声明方法           ,并绑定在子组件上

<template> <lineChart v-on:getQuotaVal="getQuotaVal"></lineChart> </template> <script> methods: { // 本事件用来监听折线图子组件              ,从子组件拿到指标数据 getQuotaVal:function(obj){ this.lineDateType = obj.lineDateType; // 这样父组件就拿到了      ,子组件的obj数据 } }, </script>

子组件触发方法

that.val = {}; that.$emit(getQuotaVal,that.val); // 将子组件的数据发送过去;

 2.4             、兄弟组件间交互

使用EventBus(事件总线)         ,vue.$bus.on和emit方法    。

初始化——全局定义              ,可以将eventBus绑定到vue实例的原型上,也可以直接绑定到window对象上.

//main.js Vue.prototype.$EventBus = new Vue();

触发事件

this.$EventBus.$emit(eventName, param1,param2,...)

监听事件

this.$EventBus.$on(eventName, (param1,param2,...)=>{     //需要执行的代码 })

移除监听事件

      为了避免在监听时         ,事件被反复触发      ,通常需要在页面销毁时移除事件监听                 。或者在开发过程中              ,由于热更新           ,事件可能会被多次绑定监听   ,这时也需要移除事件监听          。

this.$EventBus.$off(eventName);

3、v-if和v-show区别?

v-if控制Dom是否存在               ,v-show控制样式

4             、vuex是什么?使用步骤大概说下

vuex是一个状态管理工具             ,集中式的管理所有组件的状态数据  。统一的去管理组件,将组件的状态抽象为一个store文件             ,通过commit方法触发mutation里的函数来改变组件属性                。

组件中可以使用computed属性监听数据的变化控制组件显隐等             。如下举个loading组件的栗子

loading组件中根据Loading数据               ,控制DOM显隐

<template> <div class="cover" v-show="Loading"> <div>加载中</div> </div> </template> <script> import Store from ../../store export default { name: "Loading", computed:{ Loading(){ return Store.state.Loading; } } } </script>

vuex集中管理状态   ,创建一个叫store的js文件

import Vuex from vuex; Vue.use(Vuex); export default new Vuex.Store({ state: { // Loading组件 Loading:false, }, mutations: { // Loading组件 ChangeLoading:function (State,Value) { State.Loading = Value; } }, });

 使用loading的组件中           ,这样操作

import Store from ../../store Store.commit("changeFooter",true);

vuex中 mutation和action的区别和使用?

5               、vue watch和computed区别?

computed

        计算结果并返回              ,只有当被计算的属性发生改变时才会触发(即:计算属性的结果会被缓存      ,除非依赖的响应属性变化才会重新及孙)。

        如上loading组件也有使用到computed属性             。

watch

        监听某一个值         ,当被监听的值发生变化时              ,执行相关操作                。

与computed的区别是         ,watch更加适用于监听某一个值得变化      ,并做对应操作              ,比如请求后台接口等  。而computed适用于计算已有的值并返回结果          。 监听简单数据类型:

data(){ return{ first:2 } }, watch:{ first(){ console.log(this.first) } },

6   、Vue的虚拟Dom是什么?谈一谈对vue diff算法的认识?key的作用?

7           、谈谈对vue的双向绑定原理的理解?

双向绑定主要指修改数据时           ,无须操作DOM   ,视图会自动刷新                 。操作视图时绑定的数据也会跟随变动    。

数据 => 视图

vue在初始化实例时               ,会用Object.defineProperty方法             ,给所有的数据添加setter函数,实现对数据变更的监听       。当数据被修改时             ,生成新的虚拟DOM树               ,跟老的虚拟DOM对比   ,根据对比结果找出需要更新的节点进行更新                  。

视图 => 数据

从视图到数据较为简单           ,视图变化后触发监听如oninput等              ,在绑定的方法中修改数据       。

8              、vue首屏优化怎么做?

使用较轻量的组件      ,比如echart对应有vue-chart vue-cli开启打包压缩 和后台配合 gzip访问; 路由懒加载         ,分包; 打包时配置删掉log日志 资源过大可以使用cdn模式引入              ,不再打包到本地

9      、vue2的缺陷是什么?如何解决vue2.0数组中某一项改变         ,页面不改变的情况?

缺陷:数据如果为对象直接新增属性      ,如果为数组通过下标操作数组项              ,页面无法触发更新    。

原因: Vue 会在初始化实例时对 property 执行 getter/setter 转化           ,所以 property 必须在 data 对象上存在才能让 Vue 将它转换为响应式的                 。关于数组作者通过重写push/pop/shift/unshift/splice/reverse/sort这些方法来实现数据的相应绑定   ,其余的操作无法触发页面更新;

对策:关于对象可以通过Vue.$set(obj,key,value)               ,组件中通过this.$set(obj,key,value)实现新增             ,修改属性vue可以相应更新视图          。关于数组也可以通过Vue.$set(obj,key,value),或者作者重写的那些方法来操作;

10         、异步操作放在created还是mouted?

如果有些数据需要在初始化时就渲染的             ,比如select下拉框的下拉内容               ,在mouted中请求  。好处如下

页面初始化速度更快   ,减少用户等待时间 放在 created 中有助于一致性           ,因为ssr 不支持 beforeMount              、mounted 钩子函数

11         、vue-router的钩子函数有哪些?

组件内部钩子:beforeRouterEnter()      、beforeRouterLeave              、beforeRouterUpdate

12           、页面如何跳转?如何跨页面传参数?

router-link标签跳转 路由如下跳转              ,顺便把参数传了                。如下 this.$router.push({ path: /url, query: { par:parid } })

接受参数

var parid = this.$route.query.par;

13   、vue子组件的生命周期?子元素在什么时候挂载?

父:beforeCreate    首先初始化父原素 父:created              父原素挂载数据 父:beforeMounte    父原素开始挂载dom      ,tpl里遇到子组件 子:beforeCeate      子组件开始挂载数据 子:created              子元素数据挂载成功 子:beforeMount      子元素开始挂载dom 子:mounted            子元素dom挂载结束 父:mounted            父原素dom挂载结束 父:beforeUpdate     下面开始类似于dom事件流 子:beforeUpdate 子:updated 父:updated 父:beforeDestory 子:beforeDestory 子:destroyed 父:destoryed

子元素在父元素挂载dom时         ,开始加载             。子元素一直到加载完毕dom后              ,父原素结束dom挂载。后面就类似于dom事件流了             。

14               、vue的import和node的require区别?

JS支持两种模块化方式         ,commonjs和ES6                。

commonjs用于nodejs      ,同步加载模块  。ES6的import为了不卡顿              ,异步加载模块          。

新版Nodejs也支持使用import           ,但是需要修改文件后缀名为.mjs   ,或者在package.json中               ,制定type字段为module                 。

五:ES6

1             、箭头函数与es5函数区别?

箭头函数的this指向是固定的             ,普通的this指向是可变的 let a = { name: sunq, fn:function(action){ console.log(this.name + love + action); } } let b = {name:sunLi} // 正常的this指向调用他的对象 a.fn(basketball); // sunq love basketball // 改变this指向 a.fn.apply(b,[football]); // sunLi love football // 如果将a对象的fn函数改成箭头函数,this.name会是undefined // 箭头函数的this指向不会改变             ,且总是指向函数定义生效时所在的对象    。 不可以当作构造函数               ,不可以对箭头函数使用new命令   ,否则会抛出一个错误       。 var Person = function(name){ this.name = name; } let sunq = new Person(sq); // {name: sq} var Person = (name) => { this.name = name; } let sunq = new Person(sq); // 报错 Person is not a constructor 无arguments对象 不可以使用yield命令           ,因此箭头函数不能用作 Generator 函数                  。

2、ES6提供的解决异步交互的新方法?区别?

Promise             、Genarate               、async\await

3   、宏任务和微任务有哪些?执行顺序?

4           、先并行请求2个接口后              ,再请求第3个接口      ,如何处理?

使用Promise.all()方法         ,将两个promise传入all方法              ,拿到异步结果再请求第三个

明明知道的语法         ,面试官一问我偏偏就是跟实际场景联系不到一块      ,

5              、js的数据类型

string number null undefined boolean object bigInt symbol

6      、说几个ES6新增的数组的方法  详情

map 实例方法              ,类似于forEach           ,但是返回新数组

find和findIndex  实例方法   ,传入一个匿名函数               ,ruturn出符合条件的项或下标

... 拓展运算符 基本功能是将一个数组转为用逗号分隔的参数序列

7         、for in和for of的区别

for in适合遍历对象             ,遍历数组拿到的是下标 for of适合遍历数组,遍历数组直接拿到数组的项       。for of只能遍历具备iterator接口的类型    。

8              、多个数据请求             ,如何顺序执行?

使用promise的then方法               ,或者写多个promise   ,async中使用await顺序执行                 。

9         、proxy的理解           ,与defineProperty的区别?

proxy直接给所有属性设置拦截              ,defineProperty只给指定的设置 proxy拦截后要用Proxy实例调用      ,defineProperty可以直接使用原对象 // es6的proxy let obj = {name:1,sex:2} let p = new Proxy(obj,{ get:(value,key)=>{ return sq的+obj[key] } }); p.name // sq的1 p.sex // sq的2 // es5的代理 let newObj = {name:1,sex:2} Object.defineProperty(newObj,name,{ get:function(val){ //defineProperty中get函数没有入参 return sq的 + val } }) newObj.name // sq的undefined newObj.sex // 2

10      、谈谈promise的原理?

六:ElementUI

1              、如果需要修改样式怎么做?

再写一个样式表引入         ,!important覆盖 样式穿透

2           、如何通过继承扩展 element-ui 组件的功能?

通过继承扩展 element-ui 组件的功能_elementui扩展组件_在厕所喝茶的博客-CSDN博客

七:Jquery

1   、如何获取同一个cl下              ,最后一个li?

$("#id").children().eq(3).remove(); // 获取多个class中的某一个 $(".className").eq(n).attr("class") // 可行 $(".className")[n].attr("class") // 不可行

2               、window.load和$(document).ready()的区别?执行先后顺序?

window.onload必须等到页面内包括图片的所有元素加载完毕后才能执行          。 $(document).ready()是DOM结构绘制完毕后就执行         ,不必等到加载完毕  。通常简写为$()

总结:ready事件在load事件加载之前完成                。

3             、如何绑定一个点击事件?

// 方式一 $("#id").on(click,function(){}); // 方式二 $("#id").click(function(){}); // 方式三 $("#id").bind("click",function(){});

4、Jquery常用动画?

八:Git的使用

1             、常用哪些语句?

pull               、commit   、push           、reset              、merge      、log         、branch              、stash

stash如何使用?

git stash -m xxx git stash pop

2         、版本回退语句?soft和hard区别?

git reset --soft 版本号

git reset --hard 版本号

soft会退后      ,代码改动在本地还保存的有             。hard会删除本地改动              ,彻底抹去该版本的痕迹。详情

3      、合并分支注意事项?

将自己分支合到目标分支前           ,最好先将目标分支合到自己分支上处理完冲突   ,再将自己的分支合回目标分支             。

4              、如何进行分支管理?

九:敏捷开发

1           、什么是敏捷开发?

个人理解               ,敏捷开发就是把一个大需求拆为多个独立的小需求                。每个小需求可独立开发   、测试               、上线             ,循序渐进的完成整个系统  。每个版本的周期可能比较短,比如2周             ,或者4周          。

比如某公司需要开发维护一个巨大的平台               ,可能把平台外包给多个公司干                 。如果用如上方法   ,并行开发           ,可显著缩减工期    。

如果想要保证每个版本又快又顺利的上线              ,需要有完善的角色支持和流程规范       。

2             、敏捷开发的好处?

个人理解      ,当团队稍大         ,工期很紧时              ,如何有条不紊的保证版本质量就需要一套有效的流程了                  。

比如一个团队同时收到3个需求         ,每个需求分发给多个前后端开发       。作为版本负责人或者项目负责人      ,如何把控每个人的代码质量、完成进度             、过程留痕               、风险规避              ,其实是有难度的    。

一个需求如果经过           ,需求澄清   、方案设计           、设计评审              、需求传递      、版本排期/评审         、开发划分              、版本开发         、测试用例评审      、内部测试              、代码评审           、灰度试用&测试   、版本发布               、业务验收等完整的流程   ,可以有效地降低犯错的几率                 。也方便后期的查找责任人               ,总结各环节的问题             ,提升团队的工作效率,使交付越来越平稳          。

十:开源项目

部分公司面试要求中有写             ,维护有开源项目且具有50个star者优先  。

我平时有维护一个具备管理端/用户端/服务端的个人网站:sunqs blog

面试过程中无话可说时               ,可以拿出来聊聊   ,缓解尴尬                。

博客的代码全部开源:源码Github地址​​​​

十一:网络相关

1             、http和https的区别?

HTTP 明文传输           ,数据都是未加密的              ,安全性较差      ,HTTPS(SSL+HTTP) 数据传输过程是加密的         ,安全性较好             。 使用 HTTPS 协议需要到 CA(Certificate Authority              ,数字证书认证机构) 申请证书         ,一般免费证书较少      ,因而需要一定费用。证书颁发机构如:Symantec、Comodo             、GoDaddy 和 GlobalSign 等             。 HTTP 页面响应速度比 HTTPS 快              ,主要是因为 HTTP 使用 TCP 三次握手建立连接           ,客户端和服务器需要交换 3 个包   ,而 HTTPS除了 TCP 的三个包               ,还要加上 ssl 握手需要的 9 个包             ,所以一共是 12 个包                。 http 和 https 使用的是完全不同的连接方式,用的端口也不一样             ,前者是 80               ,后者是 443  。 HTTPS 其实就是建构在 SSL/TLS 之上的 HTTP 协议   ,所以           ,要比较 HTTPS 比 HTTP 要更耗费服务器资源          。

2               、常见状态码

200:成功返回 304:网页未更改有缓存              ,未重新请求 404:请求资源不在 500:服务器内部错误 503:服务器超时

十二:webpack

1   、dependencies和devDependencies区别

安装时 --save -dev会放在devDependencies中      ,--save放在dependencies

devDependencies中安装的是开发环境使用的包         ,比如eslint           、vue-cli-serve;

dependencies中安装的是生产和开发环境下都需要使用的包              ,比如vue              、element      、vant等

devDependencies中的依赖模块         ,在生产环境下不会被打入包内

十三:页面优化

1         、某个页面加载较慢      ,从哪些方向分析              、解决问题?

传统页面

首先判断是接口慢              ,还是页面慢                 。如果接口慢           ,后端优化    。

如果前端页面加载慢   ,看是否是因为图片等资源过大               ,尝试替换不同格式体积的图片       。定位是否是某些数据处理的函数             ,比较耗时                  。或者是否循环操作DOM,js生成dom后再批量插入       。

如果页面直接卡死             ,就需要分析是否内存泄漏    。比如大屏展示的定时刷新卡死               ,排查思路可如下:

使用chrome的任务管理器   ,操作页面观察的内存占用的变化                 。定位到是哪些操作           ,哪块代码导致内存占用飙升          。

因为js并没有直接释放缓存的语法              ,只有靠浏览器的垃圾回收机制自动清理  。我们需要做的是及时给不需要的变量赋空                。

特别注意大数据的循环实例化后      ,变量是否及时赋空             。定时器等闭包方法中是否存在内存泄漏         ,循环渲染地图时              ,是否先将之前地图数据清空等。

单页面应用

单页面一般不会某个页面加载慢         ,一般都集中在首屏加载时白屏较久             。处理方法可参考上文中                。

2         、使用缓存

有些接口没必要每次打开页面都请求      ,可用cookie计时  。某个时间段内不重新获取          。 某些数据初始化时加载一次即可              ,可通过cookie计时           ,某个时间段内不用请求                 。 某些数据可用localstorage存储   ,默认填充input               ,更新时才重写缓存    。这个只是用户体验好些

十四:Node.js

1      、用过哪些插件(express中间件)?

cors   解决express的跨域问题 body-parser    解析post数据 mongoClient   mongodb官方提供的Node.js驱动 crypto  用来加密             ,添加签名 nodemailer  用来发邮件

2              、mongodb和mysql的区别?

mongodb是文档型非关系型数据库,mysql是关系型数据库 mongodb以json形式存储数据             ,字段可以随意添加               ,mysql的字段需要提前确定好 mysql多表之间只能通过外键建立关系   ,mysql可以多层嵌套也可拆表并关联

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
postprocessing文件(postmaster.exe是什么进程 postmaster进程查询)