前端面试问题总结

1、说一下this指向

普通函数:谁调用就指向谁,没有调用者,就指向全局对象window。

定时器:this指向window。

箭头函数:没有this,它的this指向取决于外部环境。

构造函数:this是指向实例


2、call  apply  bind区别

相同点:改变this指向。

不同点:

call和apply会调用函数,并且改变函数内部this指向,call和apply传递的参数不一样,call传递参数使用逗号隔开,apply使用数组传递

bind不会调用函数,会改变函数内部this指向

应用场景:

call经常做继承
apply经常跟数组有关系,比如借助于数学对象实现数组最大值最小值。
bind不调用函数,但是可以改变this指向,比如改变定时器内部的this指向。

3、闭包,闭包的使用场景

闭包:定义在一个函数内部的函数(方法里面返回方法)。

闭包的使用场景:settimeout、回调、函数防抖、封装私有变量

闭包存在的意义:(1) 延长变量的生命周期;(2) 创建私有环境;

4、箭头函数,普通函数区别

外形不同:箭头函数使用箭头定义,普通函数中没有

箭头函数都是匿名函数。普通函数有匿名函数,也有具体名函数

箭头函数不能用于构造函数,不能使用new。普通函数可以用于构造函数,以此创建对象实例。

this指向不同:(1).箭头函数的 this 永远指向其上下文的 this ,任何方法都改变不了其指向,如 call() , bind() , apply()
(2).普通函数的this指向调用它的那个对象

5、防抖节流

函数防抖:在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。
应用场景:文本输入的验证;
限制 鼠标连击 触发

函数节流:每隔一段时间,只执行一次函数。
应用场景:滚动加载,加载更多或滚到底部监听。
搜索联想功能

 6、es6新特性

块级作用域和常量声明(let 和 const):ES6引入了块级作用域变量声明,通过letconst关键字可以在块级作用域中声明变量和常量,并且不会受到变量提升的影响。

箭头函数:箭头函数是一种更简洁的函数定义语法,可以使用=>替代传统的function关键字,同时具有更简洁的语法和绑定this的功能。

默认参数值:ES6允许在函数定义中为参数设置默认值,简化了函数调用时的参数传递,如果调用时未提供对应参数,则使用默认值。

扩展操作符(Spread Operator):扩展操作符允许将数组或对象展开成独立的元素,简化了数组合并、复制和对象属性扩展等操作。

解构赋值(Destructuring Assignment):解构赋值允许从数组或对象中提取值并赋给变量,可以快速获取和交换变量的值。

类和模块(Classes and Modules):ES6引入了类的概念,通过class关键字可以定义类,并使用extends进行继承。同时,ES6还引入了模块化的语法,通过exportimport关键字可以进行模块的导入和导出。

简化的对象字面量(Enhanced Object Literals):ES6允许在对象字面量中使用变量作为属性名,同时还提供了简写语法和计算属性名的支持。

迭代器和生成器(Iterators and Generators):ES6引入了迭代器和生成器的概念,可以通过自定义迭代器实现对集合的遍历,并且生成器函数可以简化异步操作的处理。

Promise对象:Promise是一种处理异步操作的新方式,可以更好地处理异步代码流程,避免回调地狱的问题。

模板字面量(Template Literals):模板字面量允许在字符串中使用类似变量插值和多行字符串的语法,通过反引号(`)包裹字符串。

7、css3新特性 

选择器:CSS3引入了新的选择器,如伪类选择器、伪元素选择器等,使得选择元素更加灵活和精确。

边框圆角:CSS3允许通过 border-radius 属性为元素的边框添加圆角,创建圆形、椭圆形或具有不同角度的矩形边框。

盒阴影:使用 box-shadow 属性,可以为元素添加投影效果,包括阴影的颜色、大小、模糊度和偏移量等。

渐变:CSS3引入了线性渐变和径向渐变,允许在元素的背景中创建平滑过渡的颜色效果。

过渡:通过使用 transition 属性,可以实现在元素状态改变时平滑地过渡属性值,如颜色、大小、位置等,提供更丰富的动画效果。

动画:CSS3的 @keyframes 规则允许创建复杂的动画效果,通过定义关键帧和过渡细节来控制动画的执行。

变形:使用 transform 属性,可以对元素进行旋转、缩放、倾斜和平移等变换操作,创造出令人惊艳的效果。

字体:CSS3提供了更多的字体控制选项,包括使用 @font-face 规则引入自定义字体文件,以及设置字体的粗细、斜体、大小调整和字间距等。

多列布局:通过 column-count 和 column-width 等属性,可以将文本内容分成多列显示,类似报纸或杂志的版面布局。

媒体查询:媒体查询允许根据设备的特性和屏幕尺寸来适应不同的样式和布局。通过媒体查询,可以创建响应式网页设计,使网页在不同设备上显示良好。

弹性盒子布局: Flexbox 是一种用于创建灵活且自适应布局的模型。它通过定义容器和项目之间的关系,实现了更简洁和可伸缩的布局方式,使得元素在不同屏幕尺寸下能够自动调整和对齐。

网格布局: Grid 布局是一个强大的二维网格系统,可用于更复杂的布局需求。它允许将页面分割为行和列,控制项目在网格中的位置和大小,实现灵活的网格布局。

过滤效果:CSS3的 filter 属性允许应用各种图形效果到元素上,如模糊、亮度调整、对比度调整、灰度化、色彩反转等,为图像和元素添加特殊的视觉效果。

8、H5新特性 

语义化标签

HTML5引入了许多新的标签,这些标签使得网页更加具有语义化,有利于搜索引擎的优化和页面的可访问性。

<article>:定义独立的文章或页面元素。

<aside>:定义文档的旁注或附加信息。

<details>:定义用户可查看或隐藏的详细信息。

<figcaption>:定义<figure>元素中的标题。

<figure>:定义带有标题的媒体对象。

<footer>:定义文档或节的页脚。

<header>:定义文档或节的页眉。

<main>:定义文档的主要内容。

<mark>:定义带有强调意义的文本。

<nav>:定义导航链接的部分。

<section>:定义文档的一个区域或节。

<summary>:定义<details>元素的摘要或标题。

<time>:定义时间或日期。

表单增强

HTML5引入了一些新的表单元素,这些元素可以帮助开发者更方便地构建表单,提供更好的用户体验。以下是HTML5中一些常用的新表单元素:

<datalist>:定义一个预定义的选项列表,用于与输入框一起使用。

<input type="color">:定义一个颜色选择器。

<input type="date">:定义一个日期选择器。

<input type="datetime-local">:定义一个本地日期和时间选择器。

<input type="email">:定义一个邮箱输入框,自带邮箱验证功能。

<input type="number">:定义一个数字输入框。

<input type="range">:定义一个范围滑块。

<input type="search">:定义一个搜索框,自带搜索建议和搜索历史功能。

<input type="tel">:定义一个电话号码输入框,自带电话号码格式验证功能。

<input type="time">:定义一个时间选择器。

<input type="url">:定义一个URL输入框,自带URL格式验证功能。

<meter>:定义一个数值范围的可视化显示。

<progress>:定义任务的进度条。

视频和音频支持

HTML5中引入了一些新的视频和音频相关的标签,以下是其中一些常用的标签:

<video>:定义一个视频。

<audio>:定义一个音频。

<source>:定义媒体文件的来源,可以使用多个<source>元素指定不同格式的媒体文件,以提高兼容性。

<track>:定义视频字幕或音频文字描述的来源。

<source>和<track>标签可以嵌套在<video>和<audio>标签中,以提供更加丰富的媒体内容。

Canvas绘图

HTML5引入了Canvas标签,可以用于在网页中绘制图形和动画。它提供了一个矩形区域,用于在其中绘制图像、文本、图形以及动态的图形和动画效果。

Web存储

HTML5提供了localStorage和sessionStorage两种本地存储方式,使得网页可以在本地存储数据,并且可以跨页面访问。

地理定位

HTML5提供了navigator.geolocation对象,可以通过浏览器获取用户的地理位置信息。

Web Workers

HTML5提供了Web Workers机制,使得网页可以通过JavaScript创建多个线程,提高页面的性能和响应速度。

Web Socket

HTML5提供了WebSocket协议,可以实现全双工通信,使得网页可以实时地和服务器进行交互。

9、vue2和vue3的区别

—  双向数据绑定原理不同

vue2vue2的双向数据绑定是利用ES5的一个APIObject.definePropert() 对数据进行劫持,结合发布订阅模式的方式来实现的。

vue3vue3中使用了ES6的Proxy API对数据代理。相比vue2.x,使用proxy的优势如下:

  • defineProperty只能监听某个属性,不能对全对象监听
  • 可以省去for in,闭包等内容来提升效率(直接绑定整个对象即可)
  • 可以监听数组,不用再去单独的对数组做特异性操作vue3.x可以检测到数组内部数据的变化。

—  是否支持碎片

vue2:vue2不支持碎片。

vue3:vue3支持碎片(Fragments) ,就是说可以拥有多个根节点。

—  API类型不同

vue2:vue2使用选项类型api,选项型api在代码里分割了不同的属性:data,computed,methods等。

vue3:vue3使用合成型api,新的合成型api能让我们使用方法来分割,相比于旧的api使用属性来分组,这样代码会更加简便和整洁。

—  定义数据变量和方法不同

vue2:vue2是把数据放入data中,在vue2中定义数据变量是data(){} ,创建的方法要在methods:{} 中。

vue3:,vue3就需要使用一个新的setup()方法,此方法在组件初始化构造的时候触发。使用以下三个步骤来建立反应性数据:

  • 从vue引入reactive
  • 使用reactive() 方法来声明数据为响应性数据;
  • 使用setup()方法来返回我们的响应性数据,从而template可以获取这些响应性数据。

—  生命周期钩子函数不同

vue2vue2中的生命周期

  • beforeCreate 组件创建之前
  • created 组件创建之后
  • beforeMount 组价挂载到页面之前执行
  • mounted 组件挂载到页面之后执行
  • beforeUpdate 组件更新之前
  • updated 组件更新之后

vue3vue3中的生命周期

  • setup 开始创建组件
  • onBeforeMount 组价挂载到页面之前执行
  • onMounted 组件挂载到页面之后执行
  • onBeforeUpdate 组件更新之前
  • onUpdated 组件更新之后

而且vue3.x 生命周期在调用前需要先进行引入。除了这些钩子函数外,vue3.x还增加了onRenderTracked 和onRenderTriggered函数。

—  父子传参不同

vue2:父传子,用props,子传父用事件 Emitting Events。在vue2中,会调用this$emit然后传入事件名和对象。

vue3:父传子,用props,子传父用事件 Emitting Events。在vue3中的setup()中的第二个参数content对象中就有emit,那么我们只要在setup()接收第二个参数中使用分解对象法取出emit就可以在setup方法中随意使用了。

—  指令与插槽不同

vue2:vue2中使用slot可以直接使用slot;v-for与v-if在vue2中优先级高的是v-for指令,而且不建议一起使用。

vue3:vue3中必须使用v-slot的形式;vue3中v-for与v-if,只会把当前v-if当做v-for中的一个判断语句,不会相互冲突;vue3中移除keyCode作为v-on的修饰符,当然也不支持config.keyCodes;vue3中移除v-on.native修饰符;vue3中移除过滤器filter

—  main.js文件不同

vue2:vue2中我们可以使用pototype(原型) 的形式去进行操作,引入的是构造函数

vue3:vue3中需要使用结构的形式进行操作,引入的是工厂函数;vue3中app组件中可以没有根标签

10、for…in 和 for…of的区别

for…of遍历获取的是对象的值(value), for…in获取的是对象的键(key);
for…in会遍历对象的整个原型链, 性能非常差不推荐使用,而for…of只遍历当前对象不会遍历原型链;
for…in循环主要是为了遍历对象而生,不适用遍历数组; for…of循环可以用来遍历数组、类数组对象、字符串、Set、Map以及Generator对象

11、简单介绍promise

Promise是ES6中的一个内置对象,实际是一个构造函数

特点:
①  三种状态:pending(进行中)、resolved(已完成)、rejected(已失败)。只有异步操作的结果可以决定当前是哪一种状态,任何其他操作都不能改变这个状态。
②  两种状态的转化:其一,从pending(进行中)到resolved(已完成)。其二,从pending(进行中)到rejected(已失败)。只有这两种形式的转变。
③  Promise构造函数的原型对象上,有then()和catch()等方法,then()第一个参数接收resolved()传来的数据,catch()第一个参数接收rejected()传来的数据

作用:
①  通常用来解决异步调用问题
②  解决多层回调嵌套的方案
③  提高代码可读性、更便于维护

 12、简单介绍async / await

①  async/await是ES7新特性
②  async/await是写异步代码的新方式,以前的方法有回调函数和Promise
③  async/await是基于Promise实现的,它不能用于普通的回调函数
④  async/await与Promise一样,是非阻塞的
⑤  async/await使得异步代码看起来像同步代码

13、Async/await 比 Promise 更优越的表现

1、简洁干净:使用 async/await 能省去写多少行代码
2、错误处理:async/wait 能用相同的结构和好用的经典 try/catch 处理同步和异步错误,错误堆栈能指出包含错误的函数。
3、调试:async/await 的一个极大优势是它更容易调试,使用 async/await 则无需过多箭头函数,并且能像正常的同步调用一样直接跨过 await 调用

总结

Async/await进一步优化了Promise.then()的缺点,使代码更简洁,所以在项目中尽量使用Async/await

14、http,https区别 

1、HTTPS协议需要CA证书,费用较高;        而HTTP协议不需要
2、HTTP协议是超文本传输协议,信息是明文传输的,HTTPS则是具有安全性的SSL加密传输协议;
3、使用不同的连接方式,端口也不同,HTTP协议端口是80,HTTPS协议端口是443;
4、HTTP协议连接很简单,是无状态的;HTTPS协议是具有SSL和HTTP协议构建的可进行加密传输、身份认证的网络协议,比HTTP更加安全

15、js哪些操作会造成内存泄露

意外的全局变量引起的内存泄露。

闭包引起的内存泄露

没有清理的DOM元素引用。

被遗忘的定时器或者回调。

子元素存在引起的内存泄露

16、什么是跨域,有哪些常见解决方案

当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域

1、jsonp方式解决跨域:

jsonp的原理就是利用了script标签不受浏览器同源策略的限制,然后和后端一起配合来解决跨域问题的。

具体的实现就是在客户端创建一个script标签,然后把请求后端的接口拼接一个回调函数名称作为参数传给后端,并且赋值给script标签的src属性,然后把script标签添加到body中,当后端接收到客户端的请求时,会解析得到回调函数名称,然后把数据和回调函数名称拼接成函数调用的形式返回,客户端解析后会调用定义好的回调函数,然后在回调函数中就可以获取到后端返回的数据了。

jsonp的优点就是兼容性好,可以解决主流浏览器的跨域问题,缺点是仅支持GET请求,不安全,可能遭受xss攻击。

2、CORS方式解决跨域:

cors是跨域资源共享,是一种基于 HTTP 头的机制,该机制通过允许服务器标示除了它自己以外的其它 origin(域,协议和端口),使得浏览器允许这些 origin 访问加载自己的资源。服务端设置了Access-Control-Allow-Origin就开启了CORS,所以这种方式只要后端实现了CORS,就解决跨域问题,前端不需要配置。

3、搭建Node代理服务器解决跨域:

因为同源策略是浏览器限制的,所以服务端请求服务器是不受浏览器同源策略的限制的,因此我们可以搭建一个自己的node服务器来代理访问服务器。

大概的流程就是:我们在客户端请求自己的node代理服务器,然后在node代理服务器中转发客户端的请求访问服务器,服务器处理请求后给代理服务器响应数据,然后在代理服务器中把服务器响应的数据再返回给客户端。客户端和自己搭建的代理服务器之间也存在跨域问题,所以需要在代理服务器中设置CORS。

4、Nginx反向代理解决跨域:

nginx通过反向代理解决跨域也是利用了服务器请求服务器不受浏览器同源策略的限制实现的。

客户端请求nginx服务器,在nginx.conf配置文件中配置server监听客户端的请求,然后把location匹配的路径代理到真实的服务器,服务器处理请求后返回数据,nginx再把数据给客户端返回。

nginx反向代理方式和node中间件代理方式的原理其实差不多,都是利用了服务器和服务器之间通信不受浏览器的同源策略的限制,但是node代理方式相对复杂一些,还要自己搭建一个node服务器,而用nginx只需要修改nginx.conf配置文件即可解决跨域问题。

5、postMessage方式解决跨域:

window.postMessage() 方法可以安全地实现跨源通信,此方法一种受控机制来规避此限制,只要正确的使用,这种方法就很安全。

主要的用途是实现多窗口,多文档之间通信:

  1. 页面和其打开的新窗口的数据传递
  2. 多窗口之间消息传递
  3. 页面与嵌套的 iframe 消息传递

具体的用法请查看:协议、域名、端口

使用postMessage向其它窗口发送数据的时候需要注意的就是,应该始终指定精确的目标 origin,而不是 *,使用window监听message事件,接收其他网站发送的 message时,请始终使用 origin 和 source 属性验证发件人的身份

6、Websocket方式解决跨域:

使用Websocket也可以解决跨域问题,因为WebSocket本身不存在跨域问题,所以我们可以利用webSocket来进行非同源之间的通信,

WebSocket 规范定义了一个在 Web 浏览器和服务器之间建立“套接字”连接的 API。 简单来说:客户端和服务器之间存在持久连接,双方可以随时开始发送数据。

17、组件通信方式有哪些

一、父与子孙通讯

  • props/emit;——父组件通过props传递数据给子组件,子组件通过$emit发送事件传递数据给父组件(单向数据流)
  • 插槽slot;
  • $parent / $children与 ref——$parent / $children访问组件实例中的方法和数据; $ref放在组件上可以获取组件实例。通过 ref 属性给子组件设置一个名字。父组件通过$refs组件名来获得子组件,子组件通过 $parent 获得父组件,这样也可以实现通信
  • v-model——语法糖(双向数据绑定)

二、跨越层级通信

  • provide / inject——使用 provide/inject,在父组件中通过 provide提供变量,在子组件中通过inject来将变量注入到组件中。不论子组件有多深,只要调用了 inject 那么就可以注入 provide中的数据【无响应性且只能单向通信(父传子)】
  • $attrs / $listeners——具有响应性且可以双向通信

三、任意组件通讯

  • 消息订阅与发布pubsub库
  • vuex状态管理——vuex 的思想就是将这一些公共的数据抽离出来,将它作为一个全局的变量来管理,然后其他组件就可以对这个公共数据进行读写操作,这样达到了解耦的目的
  • 全局事件总线bus——利用eventBus总线实现,(实际上就是新建一个vue实例,用eventBus.$emit替代this.$emit,一样用v-on监听事件变化)【使用 eventBus 的方法,它的本质是通过创建一个空的 Vue 实例来作为消息传递的对象,通信的组件引入这个实例,通信的组件通过在这个实例上监听和触发事件,来实现消息的传递。】
  • LocalStorage/SessionStorage本地存储

18、vue、小程序、uni-app中的本地数据存储和接收 

vue:
	存储:localstorage.setItem(‘key’,‘value’)
	接收:localstorage.getItem(‘key’)
 
微信小程序:
	存储:通过wx.setStorage/wx.setStorageSync写数据到缓存
	接收:通过wx.getStorage/wx.getStorageSync读取本地缓存,
 
uni-app:
	存储:uni.setStorage({key:“属性名”,data:“值”}) //异步 
		uni.setStorageSync(KEY,DATA) //同步
	接收:uni.getStorage({key:“属性名”,success(res){res.data}}) //异步
		uni.getStorageSync(KEY) //同步

19、vue , 微信小程序 , uni-app的页面生命周期函数

vue:
	beforeCreate(创建前)
	created(创建后)
	beforeMount(载入前,挂载)
	mounted(载入后)
	beforeUpdate(更新前)
	updated(更新后)
	beforeDestroy(销毁前)
	destroyed(销毁后)
小程序/uni-app: 
	1. onLoad:首次进入页面加载时触发,可以在 onLoad 的参数中获取打开当前页面路径中的参数。
	2. onShow:加载完成后、后台切到前台或重新进入页面时触发
	3. onReady:页面首次渲染完成时触发
	4. onHide:从前台切到后台或进入其他页面触发
	5. onUnload:页面卸载时触发
	6. onPullDownRefresh:监听用户下拉动作
	7. onReachBottom:页面上拉触底事件的处理函数
	8. onShareAppMessage:用户点击右上角转发

20、vue-router 有哪几种导航守卫?

全局守卫、路由独享守卫、路由组件内的守卫

//路由的钩子函数总结有6个
 
全局的路由钩子函数:beforeEach、afterEach
 
单个的路由钩子函数:beforeEnter
 
组件内的路由钩子函数:beforeRouteEnter、beforeRouteLeave、beforeRouteUpdate

21、描述cookies  sessionStorage  localStorage区别 

相同点:都存储在客户端
不同点:

1.存储大小

· cookie数据大小不能超过4k。

· sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大。

2.有效时间

· localStorage    存储持久数据,浏览器关闭后数据不丢失除非主动删除数据;

· sessionStorage  数据在当前浏览器窗口关闭后自动删除。

· cookie          设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭

3. 数据与服务器之间的交互方式

· cookie的数据会自动的传递到服务器,服务器端也可以写cookie到客户端

· sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。

22、作用域、作用域链、原型、原型链

作用域:变量和函数起作用的范围。作用域最大的用处就是隔离变量,不同作用域下的同名变量不会有冲突。

作用域链:访问变量时,自己的作用域中没有,一层一层向上寻找,直到找到全局作用域还是没找到,就宣布放弃,这种一层一层的关系,就是作用域链

原型:原型分为隐式原型和显式原型,每个对象都有一个隐式原型,它指向自己的构造函数的显式原型。每个构造方法都有一个显式原型

原型链:多个_proto_组成的集合

 23、Vue 响应式原理

核心实现类:
Observer : 它的作用是给对象的属性添加 getter 和 setter,用于依赖收集和派发更新

Dep : 用于收集当前响应式对象的依赖关系,每个响应式对象包括子对象都拥有一个 Dep 实例(里面 subs 是 Watcher 实例数组),当数据有变更时,会通过 dep.notify()通知各个 watcher。

Watcher : 观察者对象 , 实例分为渲染 watcher (render watcher),计算属性 watcher (computed watcher),侦听器 watcher(user watcher)三种

Watcher 和 Dep 的关系

watcher 中实例化了 dep 并向 dep.subs 中添加了订阅者,dep 通过 notify 遍历了 dep.subs 通知每个 watcher 更新。

依赖收集
initState 时,对 computed 属性初始化时,触发 computed watcher 依赖收集

initState 时,对侦听属性初始化时,触发 user watcher 依赖收集

render()的过程,触发 render watcher 依赖收集

re-render 时,vm.render()再次执行,会移除所有 subs 中的 watcer 的订阅,重新赋值。

派发更新
组件中对响应的数据进行了修改,触发 setter 的逻辑

调用 dep.notify()

遍历所有的 subs(Watcher 实例),调用每一个 watcher 的 update 方法。

原理
当创建 Vue 实例时,vue 会遍历 data 选项的属性,利用 Object.defineProperty 为属性添加 getter 和 setter 对数据的读取进行劫持(getter 用来依赖收集,setter 用来派发更新),并且在内部追踪依赖,在属性被访问和修改时通知变化。

每个组件实例会有相应的 watcher 实例,会在组件渲染的过程中记录依赖的所有数据属性(进行依赖收集,还有 computed watcher,user watcher 实例),之后依赖项被改动时,setter 方法会通知依赖与此 data 的 watcher 实例重新计算(派发更新),从而使它关联的组件重新渲染。

总结:

vue.js 采用数据劫持结合发布-订阅模式,通过 Object.defineproperty 来劫持各个属性的 setter,getter,在数据变动时发布消息给订阅者,触发响应的监听回调

24、Vue中computed , watch, method三者的区别 

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

Computed与methods对比

同样都可以达到计算属性的效果
1 . computed是属性调用,而methods是函数调用
2 . computed带有缓存功能,而methods不会被缓存

属性调用:
(1)、computed定义的方法我们是以属性访问的形式调用,{{computedTest}}
(2)、 methods定义的方法,我们必须要加上()来调用,{{methodTest()}}
缓存功能:
计算属性具有缓存:只有当计算属性所依赖的属性发生改变时,才会重新去计算
methods不会被缓存:方法每次都会去重新计算结果。

watch

1.watch是观察某一个属性的变化,重新计算属性的值。

2.computed是通过所依赖的属性的变化计算属性值。

3.大部分下watch和computed是没有区别的,但是如果在数据变化的同时进行异步操作的情况下,watch则是最好的选择

25、Vue 中的 key 到底有什么用? 

key 是给每一个 vnode 的唯一 id,依靠 key,我们的 diff 操作可以更准确、更快速 (对于简单列表页渲染来说 diff 节点也更快,但会产生一些隐藏的副作用,比如可能不会产生过渡效果,或者在某些节点有绑定数据(表单)状态,会出现状态错位。)

diff 算法的过程中,先会进行新旧节点的首尾交叉对比,当无法匹配的时候会用新节点的 key 与旧节点进行比对,从而找到相应旧节点.

更准确 : 因为带 key 就不是就地复用了,在 sameNode 函数 a.key === b.key 对比中可以避免就地复用的情况。所以会更加准确,如果不加 key,会导致之前节点的状态被保留下来,会产生一系列的 bug。

更快速 : key 的唯一性可以被 Map 数据结构充分利用,相比于遍历查找的时间复杂度 O(n),Map 的时间复杂度仅仅为 O(1)

26、 Vue 组件 data 为什么必须是函数 ? 

因为组件是可以复用的,JS 里对象是引用关系,如果组件 data 是一个对象,那么子组件中的 data 属性值会互相污染,产生副作用。

所以一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝。new Vue 的实例是不会被复用的,因此不存在以上问题。

27、keep-alive 的实现原理和缓存策略 

  1. 获取 keep-alive 包裹着的第一个子组件对象及其组件名
  2. 根据设定的 include/exclude(如果有)进行条件匹配,决定是否缓存。不匹配,直接返回组件实例
  3. 根据组件 ID 和 tag 生成缓存 Key,并在缓存对象中查找是否已缓存过该组件实例。如果存在,直接取出缓存值并更新该 key 在 this.keys 中的位置(更新 key 的位置是实现 LRU 置换策略的关键)
  4. 在 this.cache 对象中存储该组件实例并保存 key 值,之后检查缓存的实例数量是否超过 max 的设置值,超过则根据 LRU 置换策略删除最近最久未使用的实例(即是下标为 0 的那个 key)
  5. 最后组件实例的 keepAlive 属性设置为 true,这个在渲染和执行被包裹组件的钩子函数会用到。

28、TCP三次握手 、TCP四次挥手

  • 当有客户端需要建立连接的时候就会发送一个确定连接的报文,此报文是同步报文SYN = 1,并且会生成一个随机的序号 seq = x,这是第一次握手
  • 当服务端接收到请求连接报文的时候,会发送一个同步报文确认报文,此报文 SYN = 1,并且 ACK = 1,同时服务端也会随机生成一个 seq = y,并将 ack 设置成 x + 1,回传给客户端,这是第二次握手
  • 当客户端接收到服务端的 ACK 报文后,会回复一个 ACK 确认报文,用于确认确认报文已经收到,此报文 ACK = 1,seq = x + 1, ack = y + 1,这是第三次握手;
  • 这里有个点说明一下:大写的 ACK 表示报文的类型是确认报文,小写的 ack 是报文里面的确认号,这个确认号是上一次握手对方的 seq 值加 1 得到
  • 客户端发起 FIN 断开连接的报文,携带随机生成的 seq 值 u,发送给服务端,并且自己处于 FIN-WSIT 状态,这是第一次挥手;
  • 服务端接收到 FIN 报文后,回复一个确认报文,其中 ACK = 1,随机生成一个 seq,以及 ack = u + 1,这是第二次挥手;
  • 当服务端数据发送完了过后,再发送一个 FIN 报文给客户端,通知客户端,服务端准备关闭连接了,此报文 FIN = 1,ACK = 1,ack = u + 1,seq = w,这是第三次挥手;
  • 当客户端收到 FIN 确认报文时再发送一个FIN 的确认报文,其中 ACK = 1,seq = u + 1,ack = w + 1,并进入 TIME-WAIT 状态,当等待 2MSL 后关闭连接,这是第四次挥手。 

29、CSS link 与 @import 的区别和用法? 

  • link属于XHTML标签,除了加载CSS外,还能用于定义RSS, 定义rel连接属性等作用;而@import是CSS提供的,只能用于加载CSS;
  • 页面被加载的时,link会同时被加载,而@import引用的CSS会等到页面被加载完再加载;
  • import是CSS2.1 提出的,只在IE5以上才能被识别,而link是XHTML标签,无兼容问题

30、对事件循环的理解(详细)? 

JavaScript是一门单线程的语言,意味着同一时间内只能做一件事,但是这并不意味着单线程就是阻塞,而实现单线程非阻塞的方法就是事件循环

在JavaScript中,所有的任务都可以分为

  • 同步任务:立即执行的任务,同步任务一般会直接进入到主线程中执行
  • 异步任务:异步执行的任务,比如ajax网络请求,setTimeout定时函数等

同步任务进入主线程,即主执行栈,异步任务进入任务队列,主线程内的任务执行完毕为空,会去任务队列读取对应的任务,推入主线程执行。上述过程的不断重复就事件循环

异步任务分为微任务和宏任务:

微任务: 一个需要异步执行的函数,执行时机是在主函数执行结束之后、当前宏任务结束之前

  • Promise
  • MutaionObserver 监听dom发生改变的
  • Object.observe(已废弃;Proxy 对象替代)
  • process.nextTick(Node.js)

宏任务: 宏任务的时间粒度比较大,执行的时间间隔是不能精确控制的,对一些高实时性的需求就不太符合

  • script (可以理解为外层同步代码)
  • setTimeout/setInterval
  • postMessage、MessageChannel
  • setImmediate、I/O(Node.js)

执行顺序:

  • 先执行同步代码,
  • 遇到异步宏任务则将异步宏任务放入宏任务队列中,
  • 遇到异步微任务则将异步微任务放入微任务队列中,
  • 当所有同步代码执行完毕后,再将异步微任务从队列中调入主线程执行,
  • 微任务执行完毕后再将异步宏任务从队列中调入主线程执行,
  • 一直循环直至所有任务执行完毕

31、在地址栏输入url发生了什么? 

  1. URL解析:地址栏输入地址,浏览器对输入内容进行解析,判断URL的合法性
  2. 查找浏览器缓存:如果查找到缓存中有我们URL对应的文件,则判断是否命中强缓存,如果命中直接读取使用即可,如果强缓存没有命中,判断协商缓存是否命中,但协商缓存不论是否命中都会发送请求,所以都会走下面的步骤
  3. DNS域名解析:将输入的URL解析成对应的IP地址
  4. TCP连接:客户端与服务端进行TCP三次握手,建立连接
  5. 发送HTTP请求:握手成功后,客户端向服务端发送http请求,请求数据
  6. 服务器收到请求并返回数据:客户端根据返回的结果进行渲染展示,同时判断是否需要将文件存入缓存
  7. 页面渲染:浏览器首先会根据 html 文件构建 DOM 树,根据解析到的 css 文件构建 CSSOM 树,如果遇到 script 标签,则判端是否含有 defer 或者 async 属性,要不然 script 的加载和执行会造成页面的渲染的阻塞。
    当 DOM 树和 CSSOM 树建立好后,合并形成reader树。对reader树进行分层,为每个图层生成绘制列表,再将图层分成图块,紧接着光栅化将图块转换成位图,最后合成绘制生成页面。
  8. TCP断开连接:客户端与服务端进行TCP四次挥手,断开连接
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值