前端面试题

165 阅读7分钟
Vue组件如何通信
  1. props通信 -- 父子通信
  2. 非props的传参,$attrs -- 父子通信
  3. 事件接收器$listener -- 父子通信
  4. 事件触发$emit -- 父子通信
  5. Vuex状态管理工具 -- 任何组件
  6. provide inject 多层嵌套传参 -- 嵌套的子孙子子孙都可以
  7. vue 中的 $on emit,监听后,需在该组件销毁的时候清除,在beforeDestoryemit,监听后,需在该组件销毁的时候清除,在beforeDestory中off,避免内存泄漏 Vue3已取消(使用emit插件进行处理) -- 任何组件
  8. 使用插件eventbus、emit、happybus -- 任何组件
  9. ref通信,获取组件实例 -- 父子通信
  10. $parent $children获取组件实例
  11. slot, v-slot 作用域插槽,子组件传出,父组件接收
单页面与多页面的区别

单页面: 就是只有一份.html文件,浏览器一次加载所有文件,当url发生改变的时候不会全部刷新,只会局部刷新,前端完成页面的跳转,无需后端的支持,Vue就是单页面运用。

优点:用户体验好,好,快,内容的改变不需要重新加载整个页面,基于这一点spa对服务器压力较小;前后端分离;页面效果比较炫酷

缺点: 不利于seo;导航不可用,如果一定需要导航需要自行实现前进与后退;初次加载时耗长;页面复杂度提高很多

多页面: 多个完整页面构成,每个页面都需重新加载,整页刷新。

优点: 利于SEO,实现简单,开发成本低

缺点: 重复代码多,前后端未能完全分离

import与require的区别

impor是预编译的时候就加载进来,require是代码运行时加载进来,也有import()是返回一个promise对象,一般用在vue性能优化中的路由懒加载与异步组件。

CSS3的伪类选择器,伪元素选择器

伪类选择器::first-child,:active,:hover,:empty

伪元素选择器: ::after ::before ::first-letter ::first-line ::selection

正则表达式

' vaga ' 去首尾的空字符串:

'   vaga  '.replace(/^\s+ | \s+$/g, '')

'/hjf/jaf/dabj/abc.js'获取文件名'abc'

/(.*)\/*([^.]*)/i.exec('/hjf/jaf/dabj/abc.js')[2]
vue组件

vue组件实现代码的复用,易于维护,无需操作DOM,数据驱动视图。

vue中computed特点

computed有缓存的作用,控制这个值不发生改变,无需第二次计算获取;可接受一个函数,也可以是对象,对象中有set,get函数;computed可传参,通过闭包的形式进行传参。

Vue中的data为什么是个函数

因为vue编译出来其实是一个class, 而不是一个对象,使用vue的时候就是对其进行实例化,如果data不是 一个函数,那么数据就会被共享。

Vue的修饰符

事件修饰符:

  1. .stop:阻止冒泡
  2. .prevent:阻止默认事件发生
  3. .capture: 捕获冒泡
  4. .seft: 只有自身才能触发
  5. .once: 只触发一次
  6. .native: 绑定原生事件在该组件的父标签中的html标签上,原生事件绑定的组件中,是无法实现的,需添加.native

按键修饰符:

  1. @keyup.ctrl.exact只按ctrl键才执行。
Vue响应式

响应式,无需操作DOM,Vue帮助实现,通过Object.defineProperties拦截数据的get与set,当数据改变的时候,通过获取watch池,调用其更新,形成虚拟DOM,上个DOM与这个DOM比较,从而找出改变的地方,进行渲染即可。缺点,无法监听对象的新增与删除,无法监听数组,数组的方法需要重写。Vue3使用Proxy进行拦截,解决了Object.defineProperties的缺点。

MVVM模型

model 可以比作Vue中的data, view就是视图,你看的网页, viewModel也就是连接两个的桥梁也就是vue所做的事情。

Vue中BeforeDestory需要做什么事情
  1. 销毁自定义事件
  2. 销毁为元素绑定的事件
  3. 销毁定时器 防止内存泄漏
组件渲染与更新的过程

组件的第一次渲染时,会使用webpack的vue-loader进行解析,编译成为render函数 ,数据的响应式,执行render函数,获取变量,并把值放置watch池中收集,形成vnode,然后通过patch(ele,Vdom)形成dom,进行渲染。

更新的过程也就是触发响应式数据中的setting方法,然后订阅watch池的数据,形成新的re-Render函数,执行完形成新的Vdom,在通过patch(新的,旧的),更新视图。

自适应适配操作方式

1、使用vw、vh、100%、rem、em、微信小程序使用rpx(相对与全屏750px的1px)等相对单位进行布局。 2、rem的配置,也就是动态的给html的fontSize给值,此不考虑border的问题,是常规的适配方式:

//设计稿为1440px,1rem相当于100px(1440px设计稿)
function resizeChange(){
    const htmlEle = document.documentElement
    const radio = 14.4
    htmlEle.style.FontSize = htmlEle.getBoundingClientRect().width/radio + 'px'
}
resizeChange()
window.addEventListener('resize',resizeChange)
watch与computed区别

watch是监听数据的改变,从而执行的函数,computed则是函数里的数据改变,该computed就改变,并且其有缓存的效果,其data值不改变就不重新计算,watch只能监听简单类型,对于数组,对象中的属性无法监听,假如需要监听,则需要添加属性deep:true,假如需要首次获值也触发,则需要immediate:true即可。

Vue中事件,事件修饰符,事件对象
  1. Vue中的事件对象是原生的事件对象,Vue中若没传值,通过函数形参e,默认参数即可获取,若要传值,通过$event为最后一个传值即可,event.target即绑定事件DOM元素,event.currentTarget即触发事件的DOM元素

事件修饰符:.stop,.prevent,.self,.capture,还可以连接使用。

事件按键符:.ctrl(即使ALT或shift被一同按下时也会被触发), .ctrl.exact(有且只有CTRL被按下时触发) .exact(没有任何系统修饰符按下的时候触发)

Vue中v-if,v-show,v-for中的:key

v-if,v-show都是用来显示与不显示内容,v-if的话是重新创建与销毁,v-show是只创建一次,通过CSS中的display:none来显示与不显示, v-for 中key值不能乱写或写index,该值会影响diff算法,判定该值是否改变,每一项的特定标识。

Jacascript有几种类型
  1. 简单类型,存放在栈中,number,string,boolean,null,underfined, symbol,简单例子
let a = 10
let b = a
a = 20
console.log(b) // b = 10

  1. 引用类型,存放在栈与堆中,栈中存放的是地址,堆中存放主要的内容,有object,array,function,简单例子
let a = {a:1,b:2}
let b = a
a.a = 3
console.log(b) // b = {a:3,b:2}
深拷贝

由于上一题中对引用类型进行复制,最终改变原值的值,被赋值的值也会改变,所以对于引用类型,我们建议采用深拷贝 1、判断是简单类型,还是引用类型,typeof 即可以判断,判断值是否等于object,还有除去空对象null 2、判断是对象还是数组,通过Array.isArray()或 instanceof等判断 3、声明一个变量,在其内赋值 4、循环遍历,或其值为简单类型,直接赋值,若不是,则递归在次进入该函数,直至返回的是简单类型

javascript的内置对象

Math, //RegExp, Data Number、 String、 Boolean、Array、 Object等

null 与 undefined的区别

null是空对象,typeof null === 'object',指向的是空地址 undefined是声明了,当为赋值,再次获取会出现undefined null == undefined

什么是事件代理

事件的主要元素,事件源、事件类型、事件处理函数 事件触发有三个阶段,捕获阶段、目标阶段、冒泡阶段 捕获阶段,从外到里一层层寻找 目标阶段,找到目标的元素 冒泡阶段,从里到外一层层触发 事件代理,就是利用事件冒泡这一现象,从而实现事件代理,代理在外层的元素上。

同步与异步

JavaScript是单线程的,为了解决请求等会阻塞代码的运行,就出现了异步,异步就是不会影响代码的运行,放置另一线程,事件到了就执行 宏任务:setTimeout setInterval 微任务:Promise async await this.$nextTick Eventloop: 先执行JavaScript代码,代码里有宏任务、微任务放置微任务队列中,宏任务放置另一线程中,时机到就放置宏任务队列,待JavaScript代码全部运行完毕,触发eventLoop,监听微任务队列中是否有任务,有则放置调用栈执行,执行完微任务,查看是否需要页面更新渲染,若需要则渲染,不需要的话就再次触发eventLoop执行宏任务的队列,在循环

defer 和 async

都是并行加载script,defer会按script标签的顺序执行, async会先执行加载完毕的script代码

⾯向对象编程和⾯向过程编程
  • ⾯向对象是把构成问题事务分解成各个对象,建⽴对象的⽬的不是为了完成⼀个步骤,⽽是为了描叙某个事物在整个解决问题的步骤中的⾏为,⾯向对象是以功能来划分问题,⽽不是步骤。基本思想类、封装、继承。
  • ⾯向过程就是分析出解决问题所需要的步骤,然后⽤函数把这些步骤⼀步⼀步实现,使⽤ 的时候⼀个⼀个依次调⽤就可以了
Javascript中callee和caller的作⽤

arguments.callee()指向自己,函数递归中调用自己 b.caller()谁调用b

闭包

闭包就是函数中的私用变量,该变量在下一代函数中获取,该自由变量在函数执行完后,不会被释放,一般用于私用变量,节流防抖中可用该定时器存放在父函数中,形成私用变量,再次调用时可判断是否存在等。 可以读取函数内部的变量。 特性: 函数内再嵌套函数 内部函数可以引用外层的参数和变量 参数和变量不会被垃圾回收机制回收 优点: 可以实现封装和缓存等 缺点: 消耗内存,内存泄漏

作用域

该变量的被使用范围,有块级作用域,函数作用域,全局作用域 块级作用域: 比如{} const let声明的都是块级作用域,外层是获取不到的 全局作用域: window下的,在外层用var声明的,哪里都可以被访问到的 函数作用域: 在该函数内可被访问,其他不可,闭包例外 作用域链: 自由变量的获取,逐层向上获取,直至获取到。

javascript中的原型与原型链

javascript是基于对象与事件驱动的脚本语言,是动态语言。 原型也就是每个构造函数中都存在prototype原型,prototype存在constructor属性,该属性指向与构造函数,该原型上有共有的一些属性与方法。 每个对象中都存在__proto__属性,_ proto _指向与其构造函数中的prototype,prototype也是一个对象,对象里也存在__proto__属性,指向与其构造函数中的prototype,一层一层往上连接,直至__proto__指向null,这条链就是原型链。

javascript中如何实现继承

ES6,class中extend关键字,super关键字实现 原型链继承: Obj.prototype = new Person() Obj.prototype.constructor = Obj 构造函数继承: Obj.apply(this,a,b)

element-ui框架的按需引进

开发未开始的时候,可判断框架是按需引进,还是全局引进:

按需引进

1、vue add element

2、still proceed? y

3、Import on demand

4、zh-CN

5、app.js文件中

import { Button } from 'element-ui'
Vue.use(Button)

方便开发,先全部引入,开发完成后,修改代码,改了按需引进的步骤。

安装插件

npm install babel-plugin-component -D

//然后,将 .babelrc (Vuecli3叫 babel.config.js)修改为:
module.exports = {
	  presets: [
	    '@vue/app'
	  ],
	  plugins: [
	    [
	      'component',
	      {
	        libraryName: 'element-ui',
	        styleLibraryName: 'theme-chalk'
	      }
	    ]
	  ]
	}
//最后按需引进
import { Button } from 'element-ui'
Vue.use(Button)