vue 前端面试 题目整理

1.es5和es6的区别,说一下你所知道的es6

ES6是继ES5之后的一次改进,相对于ES5更加简洁,提高了开发效率

      1)let声明变量和const声明常量,两个都有块级作用域
       ES5中是没有块级作用域的,并且var有变量提升,在let中,使用的变量一定要进行声明

  2)箭头函数
  ES6中的函数定义不再使用关键字function(),而是利用了()=>来进行定义

  3)模板字符串
  模板字符串是增强版的字符串,用反引号(`)标识,可以当作普通字符串使用,也可以用来定义多行字符串

  4)解构赋值
  ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值

let a = 1;let b = 2;
[a,b] = [b,a];  //a=2 b=1

  5)for of循环
  for...of循环可以遍历数组、Set和Map结构、某些类似数组的对象、对象,以及字符串

let arr = [11,22,33,44,55];
let sum = 0;
for(let i=0;i<arr.length;i++){
    sum += arr[i];
}
// 将下面for循环改成for of形式
let arr = [11,22,33,44,55];
let sum = 0;
for(value of arr){
    sum += value;
}

  6)import、export导入导出
  ES6标准中,Js原生支持模块(module)。将JS代码分割成不同功能的小块进行模块化,将不同功能的代码分别写在不同文件中,各模块只需导出公共接口部分,然后通过模块的导入的方式可以在其他地方使用

// 只导入一个
import {sum} from "./example.js"

// 导入多个
import {sum,multiply,time} from "./exportExample.js"

// 导入一整个模块
import * as example from "./exportExample.js"



//可以将export放在任何变量,函数或类声明的前面
export var firstName = 'Michael';
export var lastName = 'Jackson';
export var year = 1958;

//也可以使用大括号指定所要输出的一组变量
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;
export {firstName, lastName, year};

//使用export default时,对应的import语句不需要使用大括号
let bosh = function crs(){}
export default bosh;
import crc from 'crc';

//不使用export default时,对应的import语句需要使用大括号
let bosh = function crs(){}
export bosh;
import {crc} from 'crc';

  7)set数据结构
    Set数据结构,类似数组。所有的数据都是唯一的,没有重复的值。它本身是一个构造函数

          应用场景Set用于数据重组,Map用于数据储存

  Set: 

  (1)成员不能重复
  (2)只有键值没有键名,类似数组
  (3)可以遍历,方法有add, delete,has

  Map:

  (1)本质上是健值对的集合,类似集合
  (2)可以遍历,可以跟各种数据格式转换

let arr = [12,43,23,43,68,12];
let item = [...new Set(arr)];
console.log(item);//[12, 43, 23, 68]

  8)... 展开运算符
  可以将数组或对象里面的值展开;还可以将多个值收集为一个变量

  9)修饰器 @
  decorator是一个函数,用来修改类甚至于是方法的行为。修饰器本质就是编译时执行的函数

  10)class 类的继承
      ES6中不再像ES5一样使用原型链实现继承,而是引入Class这个概念 

  11)async、await
     使用 async/await, 搭配promise,可以通过编写形似同步的代码来处理异步流程, 提高代码的简洁性和可读性
    async 用于申明一个 function 是异步的,而 await 用于等待一个异步方法执行完成

         事件循环中分为宏任务队列和微任务队列

  其中setTimeout的回调函数放到宏任务队列里,等到执行栈清空以后执行

  promise.then里的回调函数会放到相应宏任务的微任务队列里,等宏任务里面的同步代码执行完再执行

  async函数表示函数里面可能会有异步方法,await后面跟一个表达式

  async方法执行时,遇到await会立即执行表达式,然后把表达式后面的代码放到微任务队列里,让出执行栈让同步代码先执行

  12)promise
  Promise是异步编程的一种解决方案,比传统的解决方案(回调函数和事件)更合理、强大

  13)Symbol
   Symbol是一种基本类型。Symbol 通过调用symbol函数产生,它接收一个可选的名字参数,该函数返回的symbol是唯一的

         ES6 引入了一种新的原始数据类型 Symbol ,表示独一无二的值,最大的用法是用来定义对象的唯一属性名。

        ES6 数据类型除了 Number 、 String 、 Boolean 、 Objec t、 null 和 undefined ,还新增了 Symbol 

  14)Proxy代理
  使用代理(Proxy)监听对象的操作,然后可以做一些相应事情

 

2.promise/async/await的执行顺序

console.log('script start')

async function async1() {
  await async2()
  console.log('async1 end')
}

async function async2() {
  console.log('async2 end')
}
async1()

setTimeout(function() {
  console.log('setTimeout')
}, 0)

new Promise(resolve => {
  console.log('Promise')
  resolve()
})
  .then(function() {
    console.log('promise1')
  })
  .then(function() {
    console.log('promise2')
  })

console.log('script end')

上述,在Chrome 66node v10中,正确输出是:

script start
async2 end
Promise
script end
promise1
promise2
async1 end
setTimeout
  • 正常输出script start
  • 执行async1函数,此函数中又调用了async2函数,输出async2 end。回到async1函数,遇到了await,让出线程
  • 遇到setTimeout,扔到下一轮宏任务队列
  • 遇到Promise对象,立即执行其函数,输出Promise。其后的resolve,被扔到了微任务队列
  • 正常输出script end
  • 此时,此次Event Loop宏任务都执行完了。来看下第二步被扔进来的微任务,因为async2函数是async关键词修饰,因此,将await async2后的代码扔到微任务队列中
  • 执行第4步被扔到微任务队列的任务,输出promise1promise2
  • 执行第6步被扔到微任务队列的任务,输出async1 end
  • 第一轮EventLoop完成,执行第二轮EventLoop。执行setTimeout中的回调函数,输出setTimeout

 

Vue为什么要求模板只能有一个根元素

     

首先看一看template这个标签,这个标签是html5的新标签,有三个特性:

    隐藏性:不会显示在页面中
    任意性:可以写在页面的任意地方
    无效性: 没有一个根元素包裹,任何HTML内容都是无效的
每一个.Vue的单文件组件本质就是一个vue实例,既然是一个vue实例,它就要有一个入口,如果有多个div,就不无法指定这个vue实例的根入口。

就像一个HTML文档只能有一个根元素一样,多个根元素必将导致无法构成一颗树,所以解释了 <template></template>只有一个<div>根元素。 

vue 生命周期

生命周期钩子详细
beforeCreate在实例初始化之后,数据观测(data observer) 和 event/watcher 事件配置之前被调用。
created实例已经创建完成之后被调用。在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算, watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。
beforeMount在挂载开始之前被调用:相关的 render 函数首次被调用。
mountedel 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。如果 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm.$el 也在文档内。
beforeUpdate数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。你可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。
updated由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。
activatedkeep-alive 组件激活时调用。
deactivatedkeep-alive 组件停用时调用。
beforeDestroy实例销毁之前调用。在这一步,实例仍然完全可用。
destroyedVue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。

 computed和watch的区别

watch擅长处理的场景:一个数据影响多个数据

1. 不支持缓存,数据变,直接会触发相应的操作;

2.watch支持异步;

3.监听的函数接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值;

4. 当一个属性发生变化时,需要执行对应的操作;一对多;

5. 监听数据必须是data中声明过或者父组件传递过来的props中的数据,当数据变化时,触发其他操作,函数有两个参数,

  immediate:组件加载立即触发回调函数执行,

  deep: 深度监听,为了发现对象内部值的变化,复杂类型的数据时使用,例如数组中的对象内容的改变,注意监听数组的变动不需要这么做。注意:deep无法监听到数组的变动和对象的新增,参考vue数组变异,只有以响应式的方式触发才会被监听到。

computed擅长处理的场景:一个数据受多个数据影响

1. 支持缓存,只有依赖数据发生改变,才会重新进行计算

2. 不支持异步,当computed内有异步操作时无效,无法监听数据的变化

3.computed 属性值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的,也就是基于data中声明过或者父组件传递的props中的数据通过计算得到的值

4. 如果一个属性是由其他属性计算而来的,这个属性依赖其他属性,是一个多对一或者一对一,一般用computed

5.如果computed属性属性值是函数,那么默认会走get方法;函数的返回值就是属性的属性值;在computed中的,属性都有一个get和一个set方法,当数据变化时,调用set方法。

v-if和v-for哪个优先级更好,如何去优化这个问题?

    1.1 v-for的优先级会更高 (两者的渲染函数里面是可以明确的看到的)

    1.2 如果同时出现,每次渲染的时候都会先循环再判断条件,无论如何循环都不可避免,浪费了性能

    1.3 要避免这种情况出现,在外层嵌套template,把v-if加在template上 (或者先做以一次计算,只显示需要渲染的数组)

 

Vue组件的data为什么必须是个函数,而Vue的跟实例没有此限制?

    函数每次执行都会返回全新的data对象实例(initState->initData->)
    data如果是个对象,会污染其他组件的data数据
    根实例是通过new来创建的,只会创建一次,所以没有影响

vue中的key的作用和工作原理?说说对他的理解

   1.key的作用是为了更高效的更细虚拟dom,其原理是vue在patch过程中通过key可以精准判断两个节点是否是同一个,从而避免频繁更新不同的元素,是得整个patch过程更加高效,减少dom操作量,提高性能
    2.另外,若不设置key还可能在列表更新时引发一些隐蔽得bug
    3.vue中在使用相同标签名元素得过度切换时,也会使用key属性,其目的是为了让vue可以区分他们,否则vue只会替换其内部属性而不会出发过渡效果。

 

理解VUE双向数据绑定原理

1.vue 双向数据绑定是通过 数据劫持 结合 发布订阅模式的方式来实现的, 也就是说数据和视图同步,数据发生变化,视图跟着变化,视图变化,数据也随之发生改变;

2.核心:关于VUE双向数据绑定,其核心是 Object.defineProperty()方法;

3.介绍一下Object.defineProperty()方法
(1)Object.defineProperty(obj, prop, descriptor) ,这个语法内有三个参数,分别为 obj (要定义其上属性的对象) prop (要定义或修改的属性) descriptor (具体的改变方法)
(2)简单地说,就是用这个方法来定义一个值。当调用时我们使用了它里面的get方法,当我们给这个属性赋值时,又用到了它里面的set方法;



 

 

待整理  ........................

 

js 的深拷贝和浅拷贝

对于对象来说,浅复制是对对象地址的复制,并没 有开辟新的栈,也就是复制的结果是两个对象指向同一个地址,修改其中一个对象的属性,则另一个对象的属性也会改变,

而深复制则是开辟新的栈,两个对象对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性。



 

 


同级组件之间传值,store,eventBus, this.$root.$on()

keepAlived得钩子函数()

vue-route得钩子函数,以及详情
beforeRouteEnter 
beforeRouteUpdate
beforeRouteLeave
route.beforeEach
route.afterEach


vue meta权限控制

本地缓存有哪些
cook localStorage() seesionStorage() indexBD

数据双向绑定原理(vue实现原理)

事件冒泡(原理以及原生如何阻止)
.stop .default 

父子组件传值,所有得方法()
this.$emit() this.$parent props this.$chidren provide inject

原型链
每个对象都可以有一个_proto_,他会指向该对象构造函数的原型对象
prototype函数所独有的,指向对象的原型对象

js中的异步处理方式有哪几种?

1.回调函数
2.事件监听
3.观察者模式
4.promise
5.async await

js中的类型判断
1、typeof
检测不出null 和 数组,结果都为object,所以typeof常用于检测基本类型

2、instanceof
不能检测出number、boolean、string、undefined、null、symbol类型,所以instancof常用于检测复杂类型以及级成关系

3、constructor
null、undefined没有construstor方法,因此constructor不能判断undefined和null。
但是contructor的指向是可以被改变,所以不安全

4、Object.prototype.toString.call
全类型都可以判断


vue组件化的理解


虚拟dom的好处
 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值