前端面试题总结


前端面试题:

盒子水平垂直居中方法(常见)

四种方式:
利用绝对定位,先将元素的左上角通过top:50%和left:50%定位到页面的中心,然后再通过translate来调整元素的中心点到页面的中心。
利用绝对定位,设置四个方向的值都为0,并将margin设置为auto,由于宽高固定,因此对应方向实现平分,可以实现水平和垂直方向上的居中。该方法适用于盒子有宽高的情况。
利用绝对定位,先将元素的左上角通过top:50%和left:50%定位到页面的中心,然后再通过margin负值来调整元素的中心点到页面的中心。该方法适用于盒子宽高已知的情况。
使用flex布局,通过align-items:center和justify-content:center设置容器的垂直和水平方向上为居中对齐,然后它的子元素也可以实现垂直和水平的居中。

回流和重绘 (常见)

回流:当DOM的变化影响了元素的几何信息(DOM对象的位置和尺寸大小),浏览器需要重新计算元素的几何属性,将其安放在界面中的正确位置,这个过程叫做回流(重排)

重绘:

当一个元素的外观发生改变,但没有改变布局,重新把元素外观绘制出来的过程,叫做重绘
触发:
改变元素的color、background、box-shadow等属性

浏览器渲染机制

网页的生成过程,大致可以分成五步

  1. HTML 代码转化成 DOM
  2. CSS 代码转化成 CSSOM(CSS Object Model)
  3. 结合 DOM 和CSSOM,生成一棵 渲染树(包含每个节点的视觉信息)
  4. 生成布局(layout),即将所有渲染树的所有节点进行平面合成
  5. 布局绘制(paint)在屏幕上

html5新特性、语义化

html5新特性

音频video 视频 audio、画布canvas、H5存储localStorage sessionStorage

语义化标签 : header nav main article section aside footer

语义化意味着顾名思义,HTML5的语义化指的是合理正确的使用语义化的标签来创建页面结构 如 header,footer,nav,从标签上即可以直观的知道这个标签的作用,而不是滥用div。

ES6新特性

  1. let const
  2. 字符串、数组、对象的方法扩展
  3. symbol、set、map新的数据类型和数据结构
  4. proxy
  5. 异步解决方案:promise,async、await
  6. class类
  7. module模块

css盒子模型

CSS 盒模型本质上是一个盒子,盒子包裹着HTML 元素,盒子由四个属性组成,从内到外分别是:content 内容、padding 内填充、border 边框、外边距 margin

两种盒模型的区别

标准盒模型:

width = content-width
 
height = content-height

怪异盒模型:

width = content-width + padding-width + border-width
 
height = content-height + padding-height + border-height

如何在CSS 设置这两个模型

标准盒模型:

box-sizing: content-box

怪异盒模型:

box-sizing: border-box

优先级

!important > 内联 > ID 选择器 > 类选择器 > 标签选择器。

  • 每个选择器都有权值,权值越大越优先
  • 继承的样式优先级低于自身指定样式
  • 权值相同时,靠近元素的样式优先级高 顺序为内联样式表(标签内部)>内部样式表(当前文件中)> 外部样式表(外部文件中)

如何创建BFC

  1. float的值不是none。
  2. position的值不是static或者relative。
  3. display的值是inline-block、table-cell、flex、table-caption或者inline-flex
  4. overflow的值不是visible

BFC作用 (解决了什么问题)

  1. 阻止margin重叠
  2. 可以包含浮动元素 —— 清除内部浮动
  3. 自适应两栏布局
  4. 可以阻止元素被浮动元素覆盖

闭包

没有释放变量占用的内存
当一个函数的返回值是另外一个函数,而返回的那个函数如果调用了其父函数的内部变量,且返回的那个函数在外部被执行,就产生了闭包
闭包的三个特性:
1 函数套函数
2内部函数可以直接访问外部函数的内部变量或参数
3 变量或参数不会被垃圾回收机制回收

闭包的优点: 1 变量长期驻扎在内存中 2 避免全局变量的污染 3 私有成员的存在
应用场景 延时器 setTimeout 封装私有变量 函数节流 防抖

闭包的缺点: 常驻内存 增大内存

节流:函数节流(throttle)
规定在一个单位时间内,只能触发一次函数。如果这个单位时间内触发多次函数,只有一次生效。比如定时器
防抖:函数防抖(debounce)
在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。比如搜索

全局作用域和函数作用域

在代码中任何地方都能访问到的对象拥有全局作用域,一般来说以下几种情形拥有全局作用域:
最外层函数 和在最外层函数外面定义的变量拥有全局作用域
2.作用域
变量作用域:就是一个变量可以使用的范围。
js中首先有一个最外层的作用域,全局作用域;
js中可以通过函数来创建一个独立作用域称为函数作用域,函数可以嵌套,所以作用域也可以嵌套;
es6中新增了块级作用域(大括号,比如:if{},for(){},while(){}…);

作用域是在运行时代码中的某些特定部分中变量,函数和对象的可访问性。换句话说,
作用域决定了代码区块中变量和其他资源的可见性。
作用域就是一个独立的地盘,让变量不会外泄、暴露出去。也就是说作用域最大的用处就是隔离变量,不同作用域下同名变量不会有冲突。
ES6 之前 JavaScript 没有块级作用域,只有全局作用域和函数作用域。

forEach和map方法有什么区别

  • forEach()方法会针对每一个元素执行提供的函数,对数据的操作会改变原数组,该方法没有返回值;
  • map()方法不会改变原数组的值,返回一个新数组,新数组中的值为原数组调用函数处理之后的值;

注意:

  • forEach()会改变原数组的方法
  • 参数:item数组中的当前项,index当前项的索引,array原始数组;
  • 数组中有几项,那么传递进去的匿名回调函数就需要执行几次

总结:

  • 能用forEach()做到的,map()同样可以。反之亦成立
  • map()会分配内存空间存储新数组并返回,forEach()不会返回数组
  • forEach()允许callback更改原始数组的元素。而map()返回新的数组

原型

(1). prototype
每个函数都有一个prototype属性,被称为显示原型

(2)_ proto _
每个实例对象都会有_ proto _属性,其被称为隐式原型

每一个实例对象的隐式原型_ proto _属性指向自身构造函数的显式原型prototype

(3)constructor
每个prototype原型都有一个constructor属性,指向它关联的构造函数。

(4)原型链
获取对象属性时,如果对象本身没有这个属性,那就会去他的原型__proto__上去找,如果还查不到,就去找原型的原型,
一直找到最顶层(Object.prototype)为止。Object.prototype对象也有__proto__属性值为null。

这里需要注意的是Object是属于原型链的顶层,所有构造函数的的prototype都指向 Object.prototype

promise理解、手写promise

  1. Promise是异步编程的一种解决方案,它是一个对象,可以获取异步操作的消息,避免了地狱回调
  2. Promise有三种状态:pending(等待态),fulfilled(成功态),rejected(失败态);状态一旦改变,就不会再变。创造promise实例后,它会立即执行。
  3. Promise拥有一个then方法,用以处理resolved或rejected状态下的值
  4. then方法接收两个函数作为参数,第一个参数是Promise执行成功时的回调,第二个参数是Promise执行失败时的回调。
  5. then方法返回一个新的Promise对象,因此可以通过链式调用then方法
function xxx(onResolved) {
  // 这里叫做promise2
  return new Promise((resolve,inject) => {
 
    //计时器模拟请求
    setTimeout(()=>{
         if(){
             resolve(res)         
         } else{
             inject(err)         
         }  
    })
     
 
  });
};
xx.then(fun,fun)

async/await

  1. async/await函数是异步代码的新方式
  2. async/await是基于promise实现的
  3. async/await使异步代码更像同步代码
  4. await 只能在async函数中使用,不能再普通函数中使用,要成对出现
  5. 默认返回一个promise实例,不能被改变
  6. await下面的代码是异步,后面的代码是同步的

双向数据绑定

1、实现一个数据监听器Observer,能够对数据对象的所有属性进行监听,
如有变动可拿到最新值并通知订阅者
2、实现一个指令解析器 Compile,对每个元素节点的指令进行扫描和解析
,根据指令模板替换数据,以及绑定相应的更新函数
3、实现一个 Watcher,作为连接 Observer 和 Compile 的桥梁,能够订阅
并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图

vitral Dom

virtual-dom(简称vdom)的概念得益于react的出现react这个框架的非常重要的特性之一。

在vue的整个应用生命周期当中,每次需要更新视图的时候便会使用vdom

vdom算法是基于snabbdom算法所做的修改。

实现
①用js对象构造一个虚拟的dom树,插入到文档中;
②状态变更时,记录新树和旧树的差异;
③把上面的差异构建到真正的dom中

vuex

背:
vuex 是一个专门为vue.js应用程序开发的状态管理模式,它采用集中式存储和管理程序的所有组件的数据
state 存储数据
mutaitions 调用state里面的数据
actions 操作mutaitions里面的方法
getters像计算属性一样 对state里面的数据进行 逻辑性的操作
model 仓库模块化
在组件中通过dispatch来调用actions中的方法 在actions中通过commit来操作mutaitions中的方法 在mutaitions中可以调用state中的数据 数据一发生改变就会响应到组件中

keep-alive?

keep-alive是Vue提供给我们一个内置组件,他可以用来保存我们路由切换时组件的状态

组件使用keep-alive以后会新增两个生命周期 actived() deactived(),
我们在切换路由的时候,想保存组件的状态,比如列表页面进入详情,我们想保存列表滚动的位置,我们就可以使用keep-alive保存列表页面的滚动位置。
怎么使用keep-alive,有两种方式,1. 路由配置 2. keep-alive参数

  1. 全局保存在App.vue中 把包裹起来
  2. 路由定义方式

1、router.js中设置要缓存的页面

       {
            path: '/child1',
            name: 'Child1',
            component: Child1,
            meta:{
                      keepAlive:true,//保存keep-alive状态
            }
       }

      2、用v-if来显示router-view是否在keep-alive中出现
      <keep-alive>
           <router-view v-if="$route.meta.keepAlive"></router-view>
      </keep-alive> 
      <router-view v-if="!$route.meta.keepAlive"></router-view>

 3. 使用keep-alive的标签属性,  include()  exclude()
      <keep-alive  inclue="list,detail"  ></keep-alive>
      include 包含标签名字被缓存 exclude 包含的标签不被缓存

      缓存名字组件中有个name属性进行定义即可 

另一种
1、 在 vue 项目中,难免会有列表页面或者搜索结果列表页面,点击某个结果之后,返回回来时,如果不对结果页面进行缓存,
那么返回列表页面的时候会回到初始状态,但是我们想要的结果是返回时这个页面还是之前搜索的结果列表,这时候就需要用到 vue 的 keep-alive 技术了.
2、 在 router-view 上使用可以缓存该路由组件
3、 有两个参数 include - 字符串或正则表达,只有匹配的组件会被缓存
exclude - 字符串或正则表达式,任何匹配的组件都不会被缓存

组建通信

父传递子如何传递

  (1)在父组件的子组件标签上绑定一个属性,挂载要传输的变量
  (2)在子组件中通过props来接受数据,props可以是数组也可以是对象,接受的数据可以直接使用 props:["属性		名"]  props:{属性名:数据类型}

子传递父如何传递

(1)在父组件的子组件标签上自定义一个事件,然后调用需要的方法
(2)在子组件的方法中通过 this.$emit("事件")来触发在父组件中定义的事件,数据是以参数的形式进行传递的

兄弟组件如何通信

      (1)在src中新建一个Bus.js的文件,然后导出一个空的vue实例
      (2)在传输数据的一方引入Bus.js  然后通过Bus.$emit(“事件名”,"参数")来来派发事件,数据是以$emit()的参数形式来传递
      (3)在接受的数据的一方 引入 Bus.js 然后通过 Bus.$on("事件名",(data)=>{data是接受的数据})

自定义指令

【全局指令】
使用 Vue.diretive()来全局注册指令。
【局部指令】
也可以注册局部指令,组件或 Vue 构造函数中接受一个 directives 的选项。

钩子函数。指令定义函数提供了几个钩子函数(可选)。
【bind】
只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。

【inserted】
被绑定元素插入父节点时调用( 父节点存在即可调用, 不必存在于
document 中)。
【update】
所在组件的 VNode 更新时调用,但是可能发生在其孩子的 VNode 更新之前。指令的值可能发生了改变也可能没有
。但是可以通过比较更新前后的值来忽略不必要的模板更新。
【componentUpdated】
所在组件的 VNode 及其孩子的 VNode 全部更新时调用。
【unbind】
只调用一次,指令与元素解绑时调用。钩子函数参数
钩子函数被赋予了以下参数
【el】
指令所绑定的元素,可以用来直接操作 DOM。
【binding】
一个对象,包含以下属性:
name: 指令名,不包括 v- 前缀。
value: 指令的绑定值,例如: v-my-directive=“1 + 1”, value 的值是 2。oldValue: 指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
expression: 绑定值的字符串形式。例如 v-my-directive=“1 + 1” , expression
的值是 “1 + 1”。
arg: 传给指令的参数。例如 v-my-directive:foo, arg 的值是 “foo”。 modifiers: 一个包含修饰符的对象。例如: v-my-directive.foo.bar,
修饰符对象 modifiers 的值是 { foo: true, bar: true }。

路由守卫(鉴权)

路由导航守卫:
1,全局路由守卫
2,路由独享守卫
3,组件中内守卫

1,全局路由守卫
router.beforeEach 全局前置守卫
router.beforeResole 全局解析守卫
router.afterEach 全局后置守卫
2,路由独享守卫
beforeEnter 路由跳转之前 定义在路由配置上
3,组件内守卫 定义在组件内部
beforeRouteEnter beforeRouteUpdate beforeRouteLeave
路由守卫函数的参数: to 表示将要跳转到的组件 next 是一个函数 进入下一个组件的钩子函数 next(false)阻止跳转 中断导航 next(‘/login’)进入指定的组件的钩子函数

生命周期函数

背:
beforecreate创建前的阶段 date中的 数据还没有定义
created 创建后最早开始使用date和methods中的数据的钩子函数
beforemount 指令已经解析完毕内存中已经生成dom树,但是还没有渲染
mounted dom渲染完毕 可以操作dom元素
beforeupdate 当data的数据发生改变会执行这个钩子 内存更新 但是dom节点还没有更新
updated 数据更新完成以后 dom节点也已经更新完
beforedestroy 一般清除组件中的定时器或者监听的dom事件
destroyed 销毁完毕 监听器也会被移除
keepalive 方法里面
actived 组件加上keepalive 进入组件触发的方法
deactived 离开组件的时候触发的方法
errorcaptured 组件内发生错误的时候触发的方法

跨域(js,vue)

背:

跨域 :协议 域名 端口都相同的叫同域 否则都叫跨域
解决方法 jsonp ajax 请求受同源策略影响,不允许进行跨域请求,而 script 标签 src 属性中的链接却可以访问跨域的js脚本,利用这个特性,服务端不再返回JSON格式的数据,而是返回一段调用某个函数的js代码,在src中进行了调用,这样实现了跨域

(1)理解跨域的概念:协议、域名、端口都相同才同域,否则都是跨域
(2)出于安全考虑,服务器不允许 ajax 跨域获取数据,但是可以跨域获取文件内容,
所以基于这一点,可以动态创建 script 标签,使用标签的 src 属性访问 js 文件的形式获取 js 脚本,
并且这个 js 脚本中的内容是函数调用,该函数调用的参数是服务器返回的数据,为了获取这里的参数数据,
需要事先在页面中定义回调函数,在回调函数中处理服务器返回的数据,这就是解决跨域问题的jsonp原理。

跨域的解决方式有哪些?

答:产生跨域的情况有:不同协议,不同域名,不同端口以及域名和 ip 地址的访问都会产生跨域。

跨域的解决方案目前有三种主流解决方案:
是 jsonp
jsonp 实现原理:主要是利用动态创建 script 标签请求后端接口地址,然后传递 callback 参数,后端接收 callback,后端经过数据处理,
返回 callback 函数调用的形式,callback 中的参数就是 json
优点:浏览器兼容性好,
缺点:只支持 get 请求方式
是代理(前端代理和后端通常通过 nginx 实现反向代理)
前端代理我在vue 中主要是通过vue 脚手架中的config 中的index 文件来配置的,其中有个 proxyTable 来配置跨域的
前端代理核心实现通过 http-proxy-middleware 插件来实现的,vue2.x 和
vue3.x 脚手架代理跨域实现原理是一样的是 CORS
CORS 全称叫跨域资源共享,主要是后台工程师设置后端代码来达到前端跨域请求的
CORS 的原理:CORS 定义一种跨域访问的机制,可以让 AJAX 实现跨域访问。 CORS 允许一个域上的网络应用向另一个域提交跨域 AJAX 请求。
实现此功能非常简单,只需由服务器发送一个响应标头即可。

优点:无需前端工程师设置,只需后端工程师在请求的页面中配置好,并且支持所有请求方式(例如:get,post,put,delete 等)
缺点:浏览器支持有版本要求,如下:
chrome:13+,firefox:3.5+,IE 11+,edge:12+
注:现在主流框架都是用代理和 CORS 跨域实现的

常见状态码

http状态码分类:
100-199 提示信息 – 表示请求正在处理
200-299 成功 – 表示请求正常处理完毕
300-399 重定向 – 要完成请求必须进行更进一步的处理
400-499 客户端错误 – 请求有语法错误或请求无法实现
500-599 服务器端错误 – 服务器处理请求出错

常见的状态码有哪些?
① 200:请求成功,浏览器会把响应体内容(通常是html)显示在浏览器中;
② 404:(客户端问题)请求的资源没有找到 400: 语义有误,当前请求无法被服务器理解。401: 当前请求需要用户验证 403: 服务器已经理解请求,但是拒绝执行它。
③ 500:(服务端问题)请求资源找到了,但服务器内部发生了不可预期的错误;
④ 301/302/303:(网站搬家了,跳转)重定向
⑤ 304: Not Modified,代表上次的文档已经被缓存了,还可以继续使用。如果你不想使用本地缓存可以用Ctrl+F5 强制刷新页面

注意:状态码与实际情况不一致的情形

不少返回的状态码都是错误的,但是用户可能察觉不到这点,比如web应用程序发送内部错误,状态码依然返回200 OK ,这种请求也会发生的。

深拷贝 手写代码

浅拷贝 是将对象耽误每个属性进行依次复制,但是当对象的属性值是引用类型时,实质复制的是其引用,当引用指向的值改变时也会跟着变化
(浅拷贝只是拷贝了第一层属性,当第一层的属性值是基本数据类型时,新的对象和原对象互不影响,但是如果第一层的属性值是复杂数据类型,那么新对象和原对象的属性值指向的是同一块内存地址。)
浅拷贝的实现:object.assign 扩展运算符 … Array.prototype.slice() array .prototype.concat()

深拷贝 是对对象的每个属性和方法进行层层拷贝
(深拷贝是复制变量值,对于非基本类型的变量,则递归至基本类型变量后,再复制。深拷贝后的对象与原来的对象时完全隔离的,互不影响,对一个对象的修改并不会影响另一个对象。)
深拷贝实现:JSON。parse(JSON.stringify(obj))

1,对象的属性值是函数时,无法拷贝。
2,原型链上的属性无法拷贝
3,不能正确的处理 Date 类型的数据 会忽略symbol 会忽略 undefined
递归函数实现深拷贝

输入url到页面出现发生了什么

答:大致过程是这样的:

  1. DNS 解析
  2. TCP 连接
  3. 发送 HTTP 请求
  4. 服务器处理请求并返回需要的数据
  5. 浏览器解析渲染页面
  6. 连接结束

注:这里会延伸出问 http 状态码,和三次握手和四次挥手相关问题:
(1)http 状态码: 1xx(临时响应)
表示临时响应并需要请求者继续执行操作的状态代码2xx (成功)
表示成功处理了请求的状态码。
常见的 2 开头的状态码有:200 – 服务器成功返回网页3xx (重定向)
表示要完成请求,需要进一步操作。 通常,这些状态代码用来重定

常见的 3 字开头的状态码有:

301 (永久移动) 请求的网页已永久移动到新位置。 服务器返回此响应时,会自动将请求者转到新位置。
302 (临时移动) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。
304 (未修改) 自从上次请求后,请求的网页未修改过。服务器返回此响应时,不会返回网页内容。
4xx(请求错误) 这些状态代码表示请求可能出错,妨碍了服务器的处理。
常见的 4 字开头的状态有:404 – 请求的网页不存在5xx(服务器错误)
这些状态代码表示服务器在尝试处理请求时发生内部错误。 这些错误可能是服务器本身的错误,而不是请求出错。
常见的以 5 开头的状态码有:
500 (服务器内部错误) 服务器遇到错误,无法完成请求。
503 (服务不可用) 服务器目前无法使用(由于超载或停机维护)。 通常,这只是暂时状态

(2) 三次握手和四次挥手:
***三次握手:

TCP 协议中,主动发起请求的一端称为『客户端』,被动连接的一端称为『服务端』。不管是客户端还是服务端,TCP 连接建立完后都能发送和接收数据。

起初,服务器和客户端都为 CLOSED 状态。在通信开始前,双方都得创建各自的传输控制块(TCB)。
服务器创建完 TCB 后遍进入 LISTEN 状态,此时准备接收客户端发来的连接请求。

第一次握手
客户端向服务端发送连接请求报文段。该报文段的头部中 SYN=1,ACK=0, seq=x。请求发送后,客户端便进入 SYN-SENT 状态。

• PS1:SYN=1,ACK=0 表示该报文段为连接请求报文。
• PS2:x 为本次 TCP 通信的字节流的初始序号。
TCP 规定:SYN=1 的报文段不能有数据部分,但要消耗掉一个序号。

第二次握手
服务端收到连接请求报文段后,如果同意连接,则会发送一个应答:SYN=1, ACK=1,seq=y,ack=x+1。
该应答发送完成后便进入 SYN-RCVD 状态。

• PS1:SYN=1,ACK=1 表示该报文段为连接同意的应答报文。
• PS2:seq=y 表示服务端作为发送者时,发送字节流的初始序号。
• PS3:ack=x+1 表示服务端希望下一个数据报发送序号从 x+1 开始的字节。

第三次握手
当客户端收到连接同意的应答后,还要向服务端发送一个确认报文段,表示: 服务端发来的连接同意应答已经成功收到。
该报文段的头部为:ACK=1,seq=x+1,ack=y+1。
客户端发完这个报文段后便进入 ESTABLISHED 状态,服务端收到这个应答后也进入 ESTABLISHED 状态,此时连接的建立完成!
为什么连接建立需要三次握手,而不是两次握手?
防止失效的连接请求报文段被服务端接收,从而产生错误。

***TCP 四次挥手:

TCP 连接的释放一共需要四步,因此称为『四次挥手』。
我们知道,TCP 连接是双向的,因此在四次挥手中,前两次挥手用于断开一个方向的连接,后两次挥手用于断开另一方向的连接。
第一次挥手
若 A 认为数据发送完成,则它需要向 B 发送连接释放请求。该请求只有报文头,头中携带的主要参数为:
FIN=1,seq=u。此时,A 将进入 FIN-WAIT-1 状态。

• PS1:FIN=1 表示该报文段是一个连接释放请求。
• PS2:seq=u,u-1 是 A 向 B 发送的最后一个字节的序号。•

第二次挥手
B 收到连接释放请求后,会通知相应的应用程序,告诉它 A 向 B 这个方向的连接已经释放。此时 B 进入 CLOSE-WAIT 状态,并向 A 发送连接释放的应答,其报文头包含:
ACK=1,seq=v,ack=u+1。

• PS1:ACK=1:除 TCP 连接请求报文段以外,TCP 通信过程中所有数据报的ACK 都为 1,表示应答。
• PS2:seq=v,v-1 是 B 向 A 发送的最后一个字节的序号。
• PS3:ack=u+1 表示希望收到从第 u+1 个字节开始的报文段,并且已经成功接收了前 u 个字节。

A 收到该应答,进入 FIN-WAIT-2 状态,等待 B 发送连接释放请求。

第二次挥手完成后,A 到 B 方向的连接已经释放,B 不会再接收数据,A 也不会再发送数据。但 B 到 A 方向的连接仍然存在,B 可以继续向 A 发送数据。
第三次挥手
当 B 向 A 发完所有数据后,向 A 发送连接释放请求,请求头:FIN=1,ACK=1, seq=w,ack=u+1。B 便进入 LAST-ACK 状态。
第四次挥手
A 收到释放请求后,向 B 发送确认应答,此时 A 进入 TIME-WAIT 状态。该状态会持续 2MSL 时间,若该时间段内没有 B 的重发请求的话,就进入 CLOSED 状态, 撤销 TCB。当 B 收到确认应答后,也便进入 CLOSED 状态,撤销 TCB。
为什么A 要先进入TIME-WAIT 状态,等待 2MSL 时间后才进入
CLOSED 状态?
为了保证 B 能收到 A 的确认应答。
若 A 发完确认应答后直接进入 CLOSED 状态,那么如果该应答丢失,B 等待超时后就会重新发送连接释放请求,但此时 A 已经关闭了,不会作出任何响应,因此 B 永远无法正常关闭。

图片懒加载

延迟加载 比如我们加载一个页面,这个页面很长很长 长到我们额浏览器可视区域装不下 那么懒加载就是优先加载可视区域的内容 其他部分等进入了可视区在加载 所以呢一半在网页中占用资源多的都是图片 一张图片就是一个img 标签 图片的来源都是src属性 浏览器是否发起请求就是根据是否有src属性决定的 所以在没进入可视区域的时候我们先不给这个img标签赋src属性 这样浏览器就不会发送请求了
优势: 节省性能 增强用户的体验感 优化代码 服务器的按需加载减少了http的请求 并且减少了服务器的压力

nextTick

Vue中Dom的更新采取的时候异步更新队列,Vue在观察到数据变化时并不是直接跟新DOM,二十开启一个队列,并缓冲在同一时间循环中发生的所有数据改变。虽然Vue推荐我们采用数据驱动,但是有些时候我们仍然需要使用一些原生DOM操作,当数据改变后,DOM并没有立即更新,这个时候是获取不到最新的DOM对象的,nextTick就是让我们知道DOM是什么时候更新完成的,所以我们可以把DOM操作的代码放到bextTick方法中执行,也就是把代码推迟执行,在DOM更新完成后执行。
比如我们用swiper做轮播图,图片是接口获取的,发现并不轮播,一般原因就是实例化swiper的时候,DOM还没渲染完成,这个时候我们就可以把swiper的实例化放到nextTick中执行

盒子模型

标准模式下: 一个块的总宽度(页面中占的宽度)= width + margin(左右) + padding(左右) + border(左右)

怪异模式下: 一个块的总宽度= width + margin(左右)(即width已经包含了padding和border值)(IE浏览器)

为什么vue中data必须是一个函数

data是一个函数时,每个组件实例都有自己的作用域,每个实例相互独立,不会相互影响。
Object是引用数据类型,如果不用function返回,每个组件的data都是内存的同一个地址,一个数据改变了其他也改变了

数组去重

  • ES6-set
  • 利用Map数据结构去重
  • 利用递归去重
  • forEach + indexOf
  • filter+indexOf
  • forEach + includes
  • reduce + includes
  • 嵌套循环+splice
  • hash+hasOwnProperty+JSON.stringify(终级版)

for···in和for···of的区别

①从遍历数组角度来说,for···in遍历出来的是key(即下标),for···of遍历出来的是value(即数组的值);
②从遍历字符串的角度来说,同数组一样。
③从遍历对象的角度来说,for···in会遍历出来的为对象的key,但for···of会直接报错。
④如果要使用for…of遍历普通对象,需要配合Object.keys()一起使用。

javascript中的this与call/apply/bind的6关系

1,在浏览器里,在全局范围内this 指向window对象;
2,在函数中,this永远指向最后调用他的那个对象;
3,构造函数中,this指向new出来的那个新的对象;
4,call、apply、bind中的this被强绑定在指定的那个对象上;
5,箭头函数中this比较特殊,箭头函数this为父作用域的this,不是调用时的this.要知道前四种方式,都是调用时确定,也就是动态的,而箭头函数的this指向是静态的,声明的时候就确定了下来;
6,apply、call、bind都是js给函数内置的一些API,调用他们可以为函数指定this的执行,同时也可以传参。

vue项目打包

一、修改请求静态资源的路径
打开config下的index.js文件,修改assetsPublicPath的值,从‘/’改为‘./’。即从根路径改为相对路径。
build: {
// Template for index.html
index: path.resolve(__dirname, ‘…/dist/index.html’),

// Paths
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: './',
 }

二、修改本地图片的路径

打开build下的utils.js文件,增加 publicPath:’…/…/’
if (options.extract) {
  return ExtractTextPlugin.extract({
    use: loaders,
    fallback: 'vue-style-loader',
    publicPath:'../../'
  })
} else {
  return ['vue-style-loader'].concat(loaders)
}

三、在终端运行npm run build。

防抖和节流

防抖: 触发高频事件后 定时器内函数只会执行一次,如果定时器内高频事件再次被触发,则重新计算时间 比如:搜索
场景:
按钮提交场景:防止多次提交按钮,只执行最后提交的一次。
节流 :高频事件触发,在定时器内只会执行一次,所以节流会稀释函数的执行效率。
1.拖拽场景:固定时间内只执行一次,防止超高频次触发位置变动
2.缩放场景:监控浏览器 resize
3.动画场景:避免短时间内多次触发动画引起性能问题

Git指令

git init 初始化git仓库
git status 查看文件状态
git add 文件列表 追踪文件
git commit -m 提交信息 向仓库中提交代码
git log 查看提交记录
覆盖工作目录中的文件: git checkout --文件名
将文件从暂存区中删除: git r m --cached 文件名
git branch 查看分支
git branch 分支名称 创建分支
git checkout 分支名称 切换分支
git merge 来源分支 合并分支 (必须在master分支上才能合并d)
git branch -d 分支名称 删除分支(分支被合并后才允许删除)(-D 强制删除)
将本地仓库推送到远程仓库: git push 项目链接
Git 添加远程仓库origin (origin是仓库别名): git remote add 仓库名 项目链接
git push origin master
git push -u origin master
-u 将推送地址和分支保存,下次推送输入git push即可

什么是内存泄漏

程序的运行需要内存。只要程序提出要求,操作系统或者运行时就必须供给内存。
对于持续运行的服务进程,必须及时释放不再用到的内存。否则,内存占用越来越高,轻则影响系统性能,重则导致进程崩溃。

原生Ajax的创建过程

1.创建xhr 核心对象
2.调用open 准备发送
3.如果是post请求,必须设置请求头。
4.调用send 发送请求 (如果不需要参数,就写null)
5.监听异步回调
备注:如果是post请求,想要传json格式数据。

事件冒泡,事件捕获,事件流

事件冒泡:事件冒泡会从当前触发的事件目标一级一级往上传递,依次触发,直到document为止。
事件捕获:事件捕获会从document开始触发,一级一级往下传递,依次触发,直到真正事件目标为止。
事件流:DOM结构是一个树型结构,当一个HTML元素产生一个事件时,该事件会在元素结点与根结点之间的路径传播,路径所经过的结点都会收到该事件,这个传播过程可称为DOM事件流。

阻止事件冒泡

1.event.stopPropagation();
事件处理过程中,阻止了事件冒泡,但不会阻击默认行为
2.return false;
事件处理过程中,阻止了事件冒泡,也阻止了默认行为
还有一种有冒泡有关的:
3.event.preventDefault();
它的作用是:事件处理过程中,不阻击事件冒泡,但阻击默认行为

箭头函数与普通函数区别

箭头函数是匿名函数不能作为构造函数不能使用new
箭头函数不绑定arguments,需要用运算符解决…解决
箭头函数不绑定this,会捕获其所在的this值,作为自己的this值
箭头函数通过call()或apply()调用一个函数,只传入了一个参数,对this并没有影响.
箭头函数没有原型属性

let、const、var 的区别

  • var声明的变量存在变量提升,变量可以声明之前调用
  • let和const不存在变量提升 let和const存在暂时性死区
  • var允许重复声明变量, let和const在同一作用域不允许重复声明变量
  • var不存在块级作用域,let和const存在块级作用域.
  • var和let可以修改声明变量 const声明的变量不能改变一但改变立即初始化,不能留到以后赋值

单向数据流和双向绑定

1.Vue 在不同组件间强制使用单向数据流,父组件可以向子组件传递数据,但是子组件不能直接修改父组件的状态。
2.数据的双向绑定
主要由MVVM框架实现,主要由三部分组成View、ViewModel和Model组成,其中view和model不能直接进行通信,他们通过中间件ViewModel来进行通信。

methods computed watch的区别

computed 具有缓存性,依赖于属性值,只有属性发生改变的时候才会重新调用
methods 是没有缓存的,只要调用,就会执行,一般结合事件来使用
watch 没有缓存性 监听data中的属性 属性值只要发生变化就会执行 可以利用他的特性做一些异步的操作

1 . computed 属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算。主要当作属性来使用;
2 . methods 方法表示一个具体的操作,主要书写业务逻辑;
3 . watch 一个对象,键是需要观察的表达式,值是对应回调函数。主要用来监听某些特定数据的变化,从而进行某些具体的业务逻辑操作;可以看作是 computed 和 methods 的结合体;

diff算法

基础虚拟DOM完成节点更新的方法
1. 用js对象来表示真实的DOM树结构,创建一个虚拟DOM对象
2. 当数据发生改变的时候,创建一个新的js的虚拟DOM对象
3. 比较新旧对象的差异,记录下来,最终更新到真实的DOM树结构上

如何让CSS只在当前组件中起作用?

将当前组件的<style>修改为<style scoped>

请描述一下 cookies sessionStorage和localstorage区别(常见)

1.cookie的作用是与服务器交互,作为http规范的一部分,而localStorage是为了本地存储数据而诞生的;
2.cookie会将数据发给服务器,web storage仅在本地保存;
3.cookie的数据大小限制为4k,同一域名下的cookie数量限制为20个,localStorage数据大小限制为5M;
4.localStorage存储持久数据,浏览器关闭后数据不丢失除非手动删除,sessionStorage数据在当前窗口关闭后自动删除,cookie设置的过期时间之前一直有效,即使窗口或浏览器关闭;
5.sessionStorage在打开不同的浏览器窗口不共享,即使是同一页面,localStorage在同源页面是共享的,cookie在同源页面是共享的。
cookie 设置过期时间 在有效期内不会自动删除 4k
localStorage 如果没有手动删除 浏览器关掉了也不会被删掉 5M
sessionStorage 浏览器关掉之后就会自动被删掉 5M

简要说明 iframe 的优缺点?

iframe的优点:

① iframe能够原封不动地把嵌入的网页展现出来。

② 如果有多个网页调用iframe,只需要修改iframe的内容,就可以实现对调用iframe的每一个页面内容的更改,方便快捷。

③ 网页如果为了统一风格,头部和版本都是一样的,就可以写成一个页面,用iframe来嵌套,可以增加代码的可重用性。

④ 如果图标和广告遇到加载缓慢的第三方内容可以用iframe来解决。

iframe的缺点:

① 会产生很多页面,不容易管理

② 在几个框架中都出现上下、左右滚动条时,这些滚动条除了会挤占已经非常有限的页面空间外,还会分散访问者的注意力。

③ 使用框架结构时,必须保证正确设置所有的导航链接,否则会给访问者带来很大的麻烦。比如被链接的页面出现在导航框架内,这种情况下会导致链接死循环

④ 很多的移动设备(PDA手机)无法完全显示框架,设备兼容性差。

⑤ iframe框架页面会增加服务器的http请求,对于大型网站是不可取的。

现在基本上都是用Ajax来代替iframe,iframe已渐渐退出了前端开发。

数组去重

*排序sort
*set 去重
*filter 过滤
*indexOf
*利用includes 方法 当result 数组中没有值时添加进去
*五. 利用indexOf 方法 有重复时会返回第一个数的下标 没找到时返回-1

0.1+0.2大于还是等于还是小于0.3

例子:

console.log(0.1+0.2) // 结果0.30000000000000004 而不是0.3

原因:

在计算机中数字无论是定点数还是浮点数都是以多位二进制的方式 进行存储的。
在JS中数字采用的IEEE 754的双精度标准进行存储(存储一个数值所使用的二进制位数比较多,精度更准确)

解决办法

想办法规避掉这类小数计算时的精度问题就好了,那么最常用的方法就是将浮点数转化成整数计算。因为整数都是可以精确表示的。

0.1+0.2 => (0.110+0.210)/10

Map和filter有什么不同

对于map和filter有时候傻傻分不清楚,不管jquery,只说js中的两个方法,map()和filter()都是对调用他们的数组进行遍历。

首先熟悉一下他们的使用方法:
arr.map(function (item,index,array){……})
arr.filter(function (item,index,array){……})
都是将函数写在方法的括号里,参数也一样
参数:
item:当前处理的元素;index:当前处理元素的索引;array:调用map方法的数组,也就是arr

map的结果只是对当前元素调用函数后(x是否大于1)的结果。而filter 会将结果为true的数组存到新的数组里面。

== 和 === 的区别

1、对于string,number等基础类型,=是有区别的
1)不同类型间比较,==之比较“转化成同一类型后的值”看“值”是否相等,===如果类型不同,其结果就是不等
2)同类型比较,直接进行“值”比较,两者结果一样

2、对于Array,Object等高级类型,=是没有区别的
进行“指针地址”比较

3、基础类型与高级类型,=是有区别的
1)对于==,将高级转化为基础类型,进行“值”比较
2)因为类型不同,===结果为false

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值