文章目录
- 1.Vue2和Vue3的区别至少说5点
- 2.Vue3中组件通信的流程[父传子,子传父]
- 3. Apply/call/bind的原理是什么?
- 4. 说说你对原型和原型链的理解?
- 5. 说说你对ES6中Generator的理解
- 6. 说说你对Event Loop的理解
- 7. 说说Promise和async/await 的区别?
- 8. 说说浏览器事件循环和nodeJs的事件循环的区别?
- 9. 说说你对浏览器缓存机制的理解
- 10. 说说你对浏览器内核的理解
- 11. 说说你对Vue的响应式原理的理解
- 12. Methods watch computed区别是什么?
- 13. 说说你对Virtual DOM的理解?
- 14. 说说你对nextTick的理解和作用
- 15. 说说你对webpack的理解
- 16. 谈谈GET和POST的区别
- 17. 说说HTTP和HTTPS的区别,HTTPS加密原理是?
- 18. TCP为什么要三次握手?
- 19. 说说Proxy代理的原理
- 20. 说说内存泄漏的理解?内存泄漏的情况有哪些?
1.Vue2和Vue3的区别至少说5点
1). vue2和vue3双向数据绑定原理发生了改变
- vue2的双向数据绑定是利用了es5 的一个API Object.definepropert() 对数据进行劫持 结合发布订阅模式来实现的。vue3中使用了es6的proxyAPI对数据进行处理。
- 相比与vue2,使用proxy API 优势有:defineProperty只能监听某个属性,不能对全对象进行监听;可以省去for in 、闭包等内容来提升效率(直接绑定整个对象即可);可以监听数组,不用再去单独的对数组做特异性操作,vue3可以检测到数组内部数据的变化。
2).Vue3支持碎片(Fragments)
就是说可以拥有多个跟节点。
3).Composition API(组合API)
Vue2 与vue3 最大的区别是vue2使用选项类型api,对比vue3合成型api。旧得选项型api在代码里分割了不同得属性:data,computed,methods等;新得合成型api能让我们使用方法来分割,相比于旧的API使用属性来分组,这样代码会更加简便和整洁。
4).建立数据data
vue2是把数据放入data中,vue3就需要使用一个新的setup()方法,此方法在组件初始化构造得时候触发。使用一下三个步骤来简=建立反应性数据: 1. 从vue引入reactive; 2. 使用reactive() 方法来声明数据为响应性数据; 3. 使用setup()方法来返回我们得响应性数据,从而template可以获取这些响应性数据。
5).生命周期
vue2 --------------> vue3
beforeCreate -> setup()
Created -> setup()
beforeMount -> onBeforeMount
mounted -> onMounted
beforeUpdate -> onBeforeUpdate
updated -> onUpdated
beforeDestroyed -> onBeforeUnmount
destroyed -> onUnmounted
activated -> onActivated
deactivated -> onDeactivated
6). 父子传参不同,setup()函数特性
- setup()函数接收两个参数:props、context(包含attrs、slots、emit)
- setup函数是处于生命周期beforeCreated和created俩个钩子函数之前
- 执行setup时,组件实例尚未被创建(在setup()内部,this不会是该活跃实例得引用,即不指向vue实例,Vue为了避免我们错误得使用,直接将setup函数中得this修改成了undefined)
- 与模板一起使用时,需要返回一个对象
- 因为setup函数中,props是响应式得,当传入新的prop时,它将会被更新,所以不能使用es6解构,因为它会消除prop得响应性,如需解构prop,可以通过使用setup函数中得toRefs来完成此操作。
- 父传子,用props,子传父用事件 Emitting Events。在vue2中,会调用this$emit然后传入事件名和对象;在vue3中得setup()中得第二个参数content对象中就有emit,那么我们只要在setup()接收第二个参数中使用分解对象法取出emit就可以在setup方法中随意使用了。
- 在setup()内使用响应式数据时,需要通过 .value 获取
import { ref } from 'vue'
const count = ref(0)
console.log(count.value)
- 从setup() 中返回得对象上得property 返回并可以在模板中被访问时,它将自动展开为内部值。不需要在模板中追加.value。
- setup函数只能是同步的不能是异步的。
2.Vue3中组件通信的流程[父传子,子传父]
一.Vue3 组件通讯 – 父传子 方法流程
- 在父组件中引入子组件
import 子组件名 from '子组件路径'
- 使用子组件
<子组件名> </子组件名>
- 父组件给子组件添加属性传值
// 注意: 加 : 号表示可以使用 Vue3.x 内属性
<子组件名 :自定义属性名=" 变量名/属性值 "> </子组件名>
- 子组件内 通过 defineProps 属性接收
//注意: 子组件位置一般在 src/components 内 script
//script标签 内想要访问传值数据 props.自定义属性名
const props = defineProps({
自定义属性名:{
type: 数据类似,
default: 默认值
}
})
//注意: 如果使用defineProps接收数据 这个数据只能在模版中渲染 如果要在script内操作 defineProps 内属性 应该 定义变量名 接收返回值
流程总结:
- 父组件提供数据
- 父组件将数据传递给子组件
- 子组件通过 defineProps 进行接收
- 子组件渲染父组件传递的数据
二.Vue3 组件通讯 – 子传父 方法流程
- 首先子组件通过 defineEmit 写入传递事件名 并 定义变量名
const 变量名one = defineEmit([' 传递事件名'])
- 子组件通过 defineEmit 定义的变量名 触发触发事件 并 传递数据 逗号后面是参数
const 变量名two = ( ) => { 变量名one('传递事件名',参数1,参数2 ) }
- 父组件接收传递来的变量名 并 提供方法
<子组件 @传递事件名="方法名"> </子组件>
- 使用标签内定义 方法 并 定义参数 接收子组件传参
const 变量名three = (参数名) => { console.log(参数名) }
总结:
- 子组件通过defineEmit获取emit对象
- 子组件通过emit触发事件 并传递数据
- 父组件提供方法
- 父组件通过自定义事件的方式给子组件注册事件
3. Apply/call/bind的原理是什么?
apply,call,bind三者的区别?
1、三者都可以改变函数的this对象指向。
2、三者第一个参数都是this要指向的对象,如果如果没有这个参数或参数为undefined或null,则默认指向全局window。
3、三者都可以传参,但是apply是数组,而call是参数列表,且apply和call是一次性传入参数,而bind可以分为多次传入。
bind 是返回绑定this之后的函数,便于稍后调用;apply 、call 则是立即执行 。
原理?
call、apply 和 bind 是挂在 Function 对象上的三个方法,调用这三个方法的必须是一个函数、
func.call(thisArg, param1, param2, ...)
func.apply(thisArg, [param1,param2,...])
func.bind(thisArg, param1, param2, ...)
- 在浏览器里,在全局范围内this 指向window对象;
- 在函数中,this永远指向最后调用他的那个对象;
- 构造函数中,this指向new出来的那个新的对象;
- call、apply、bind中的this被强绑定在指定的那个对象上;
- 箭头函数中this比较特殊,箭头函数this为父作用域的this,不是调用时的this.要知道前四种方式,都是调用时确定,也就是动态的,而箭头函数的this指向是静态的,声明的时候就确定了下来;
- apply、call、bind都是js给函数内置的一些API,调用他们可以为函数指定this的执行,同时也可以传参
4. 说说你对原型和原型链的理解?
原型
JavaScript 常被描述为一种基于原型的语言——每个对象拥有一个原型对象
当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾
准确地说,这些属性和方法定义在Object的构造器函数(constructor functions)之上的prototype属性上,而非实例对象本身
原型对象有一个自有属性constructor,这个属性指向该函数,如下图关系展示
原型链
原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。这种关系常被称为原型链 (prototype chain),它解释了为何一个对象会拥有定义在其他对象中的属性和方法
在对象实例和它的构造器之间建立一个链接(它是__proto__属性,是从构造函数的prototype属性派生的),之后通过上溯原型链,在构造器中找到这些属性和方法
分析:
- 构造函数Person存在原型对象Person.prototype
- 构造函数生成实例对象person,person的__proto__指向构造函数Person原型对象
- Person.prototype.proto 指向内置对象,因为 Person.prototype 是个对象,默认是由 Object函数作为类创建的,而 Object.prototype 为内置对象
- Person.proto 指向内置匿名函数 anonymous,因为 Person 是个函数对象,默认由 Function 作为类创建
- Function.prototype 和 Function.__proto__同时指向内置匿名函数 anonymous,这样原型链的终点就是 null
总结:
5. 说说你对ES6中Generator的理解
Generator 函数是 ES6 提供的一种异步编程解决方案
执行 Generator 函数会返回一个遍历器对象,可以依次遍历 Generator 函数内部的每一个状态
形式上,Generator 函数是一个普通函数,但是有两个特征:
- function 关键字与函数名之间有一个星号
- 函数体内部使用 yield 表达式,定义不同的内部状态
Generator 函数会返回一个遍历器对象,即具有 Symbol.iterator 属性,并且返回给自己
通过 yield 关键字可以暂停 generator 函数返回的遍历器对象的状态
6. 说说你对Event Loop的理解
首先,JavaScript是一门单线程的语言,意味着同一时间内只能做一件事,但是这并不意味着单线程就是阻塞,而实现单线程非阻塞的方法就是事件循环
在JavaScript中,所有的任务都可以分为同步任务和异步任务
- 同步任务:立即执行的任务,同步任务一般会直接进入到主线程中执行
- 异步任务:异步执行的任务,比如ajax网络请求,setTimeout定时函数等
可以看出,同步任务进入主线程,即主执行栈,异步任务进入任务队列,主线程内的任务执行完毕为空,会去任务队列读取对应的任务,推入主线程执行。上述过程的不断重复就事件循环
7. 说说Promise和async/await 的区别?
- promise和 async/await都是解决异步编程的一种方式,但是async/await使得异步代码看起来像同步代码。
- 函数前面多了一个async关键字。await关键字只能用于async定于的函数内。async函数会隐式地返回一个Promise,该promise的resolve值就是return的值。
为什么async/await更好?
使用async函数可以让代码简洁很多,不需要像Promise一样需要then,不需要写匿名函数处理Promise的resolve的值,也不需要定义多余的data变量,还避免了嵌套代码
async/await 让 try/catch可以同时处理同步和异步的错误。在下面的示例中,try/catch不能处理JSON.parse的错误,因为它在Promise中,我们需要使用.catch,这样的错误会显得代码非常的冗余
8. 说说浏览器事件循环和nodeJs的事件循环的区别?
浏览器事件循环机制中,微任务的任务队列是在每个宏任务执行完之后执行。
Node事件循环机制中,微任务会在事件循环的各个阶段之间执行,也就是说,一个阶段执行完毕,就会去执行微任务队列的任务。
9. 说说你对浏览器缓存机制的理解
是浏览器在本地对请求过的文档进行了一个缓存,当再次访问的时候,浏览器可以从本地缓存的文档进行加载,缓存又分为强缓存和协商缓存
强缓存就是不会像服务器发送请求,直接从缓存中读取资源,在控制台的网络中可以看到一个请求返回200 的状态码
协商缓存就是会向服务器发送请求,服务器会根据这个请求的请求头携带的一些参数来判断是否命中协商缓存,如果命中,就返回304 状态码并携带上新的请求头通知浏览器从缓存中读取资源
10. 说说你对浏览器内核的理解
主要分为两部分:渲染引擎和js引擎。
渲染引擎:是负责取得网页的内容(html、xml、图像等),整理讯息(比如加入css等),以及计算网页的显示方式,然后会输出到显示器或者打印。 浏览器的内核不同,对网页语法的解释也就不同,渲染的效果就不同。所有的浏览器等以及需要编辑,显示网络内容的应用程序需要内核。
js引擎:则用来解析JavaScript来实现网页的动态效果
最开始两个引擎区分不是很明确,后来js引擎越来越独立,内核就倾向于只能渲染引擎。
11. 说说你对Vue的响应式原理的理解
响应式基本原理是基于Object.defineProperty(obj, prop, descriptor), descriptor里面可以定义get和set方法,可以在获取属性值事触发get方法(可以收集依赖),设置属性值时触发set方法(更新依赖)
扩展:上面是vue2.0的响应式基本原理,vue3.0的基本原理是Proxy,可以监听属性的get和set方法,监听属性的添加和删除等等,比Object.defineProperty能力更强,但是不兼容IE11。
12. Methods watch computed区别是什么?
Methods是一个方法,是一个封装好的函数,不管是否有变化,只要一触发就会去执行
Computed是一个计算属性,可以对data中的依赖项重新计算得到一个新的值,应用到视图中,和methods的本质区别是,computed是可缓存的,当computed中的依赖项如果没有变化,那么computed中的值不会重新计算,而methods是没有缓存的
Watch:是深度监听,监听data和计算属性computed的新旧变化
13. 说说你对Virtual DOM的理解?
虚拟dom其实就是以可虚拟的js对象,以对象的属性来描述节点,实际上他只是真实dom的一层抽象,最终通过一系列的操作将这棵树映射到真实环境上
在js对象中,并且最少包含了标签属性和签名这三个属性,不同的框架对这三个属性的定义也会有所不同
14. 说说你对nextTick的理解和作用
vue的$nextTick其本质是对js执行原理EventLoop的一种应用
$nextTick的核心是利用promise,mutationObserver、setImmediate、setTimeout的原生javascript方法来模拟对应的微/宏任务的实现,本质是为了利用JavaScript的这些异步回调任务队列来实现vue框架中自己的异步回调队列。
nextTick是典型的将底层的javascript执行原理应用到具体案例中的示例,引入异步更新队列机制的原因:
- 如果是同步更新,则多次对一个或者多个属性赋值,会频繁触发dom的渲染,可以减少一些无用的渲染。
- 同时由于virtualDom的引入,每一次状态发生变化之后,状态变化的信号会发送给组件,组件内部使用virtualDom进行计算得出需要更新的具体的dom节点,然后对dom进行更新操作,每次更新状态后的渲染过程需要更多的计算,而这种无用功也将浪费更多的性能,所以异步渲染变得更加至关重要。
- vue采用了数据驱动的思想,但是在一些情况下,仍然需要操作dom。有时候,可能遇到这样的情况,dom1的数据发生了变化,而dom2需要从dom1中获取数据,那这时候就会发现dom2的试图并没有更新,这时就需要用到nextTick了。
15. 说说你对webpack的理解
WebPack 是一个模块打包工具,可以使用WebPack管理模块,并分析模块间的依赖关系,最终编绎输出模块为HTML、JavaScript、CSS以及各种静态文件(图片、字体等),让开发过程更加高效。
webpack的基本功能(也就是各种loader的作用)
-
代码转换:TypeScript 编译成 JavaScript、ES6转ES5、SCSS 编译成 CSS 等等(各种loader)
-
代码语法检测:自动检测代码是否符合语法 (eslint-loader)
-
代码分割:打包代码时,可以将代码切割成不同的chunk(块),实现按需加载,降低了初始化时间,提升了首屏渲染效率
-
监测代码更新,自动编译,刷新页面:监听本地源代码的变化,自动构建,刷新浏览器(自动刷新)
-
自动发布:更新完代码后,自动构建出线上发布代码并传输给发布系统(没用过)。
-
文件压缩:压缩 JavaScript、CSS、HTML 代码,缩小文件体积(比如说,打包后的js、css、html文件会去掉代码之间的空隔,紧凑显示)
-
模块合并:由于模块化的开发,一个页面可能会由多个模块组成,所以编译时需要把各个模块合并成一个文件(模块化开发引出的功能)
webpack的两大特色
- 自动分割(code splitting)
code splitting,即打包代码时,可以将代码切割成不同的chunk(块),实现按需加载,降低了初始化时间,提升了首屏渲染效率
- loader 加载器可以处理各种类型的静态文件,并且支持串联操作
16. 谈谈GET和POST的区别
GET产生一个TCP数据包;POST产生两个TCP数据包。
对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);
而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。
因为POST需要两步,时间上消耗的要多一点,看起来GET比POST更有效
GET与POST都有自己的语义,不能随便混用。
据研究,在网络环境好的情况下,发一次包的时间和发两次包的时间差别基本可以无视。而在网络环境差的情况下,两次包的TCP在验证数据包完整性上,有非常大的优点。
并不是所有浏览器都会在POST中发送两次包,Firefox就只发送一次。
17. 说说HTTP和HTTPS的区别,HTTPS加密原理是?
HTTP协议以明文方式发送内容,不提供任何方式的数据加密。HTTP协议不适合传输一些敏感信息,比如:信用卡号、密码等支付信息。https则是具有安全性的ssl加密传输协议。http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。并且https协议需要到ca申请证书。HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全。
HTTPS加密原理:
加密原理?点此查看详情
18. TCP为什么要三次握手?
1、所谓的三次握手:为了对每次发送的数据量进行跟踪与协商,确保数据段的发送和接收同步,根据所接收到的数据量而确认数据发送、接收完毕后何时撤消联系,并建立虚连接。
2、为了提供可靠的传送,TCP在发送新的数据之前,以特定的顺序将数据包的序号,并需要这些包传送给目标机之后的确认消息。TCP总是用来发送大批量的数据。当应用程序在收到数据后要做出确认时也要用到TCP
总结:
- 三次握手才可以阻止重复历史连接的初始化(主要原因)
- 三次握手才可以同步双方的初始序列号
- 三次握手才可以避免资源浪费
19. 说说Proxy代理的原理
用户在浏览器中设定 Proxy之后,用户通过浏览器访问 WWW网站的请求不会直接发送到目标主机,而是发送到代理服务器上,代理服务器接收到用户的请求,接收到目标主机的数据,存储到代理服务器的硬盘中,再将用户需要的信息发送到用户的服务器上。
20. 说说内存泄漏的理解?内存泄漏的情况有哪些?
内存泄漏是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果
内存泄漏的几种场景
- 全局变量过多 通常是变量未被定义或者胡乱引用了全局变量
- 闭包 未手动解决必包遗留的内存引用。定义了闭包就要消除闭包带来的副作用。
- 事件监听未被移除
- 缓存 建议所有缓存都设置好过期时间