欢迎来到沐沐的博客

前端面试题(持续更新...)

HTML篇

cookie,localStorage,sessionStorage的区别

  • 存储大小:cookie40kb左右,Storage20M左右
  • 存储格式:cookie是字符串格式,Storage是键值对
  • 通讯相关:cookie随请求携带,Storage不会自动携带
  • 操作相关:cookie操作复杂,没有api前后端都可以操作;Storage操作简单,有api,只能前端操作。
  • 时效相关:cookie默认是会话,可以手动设置;localStorage的存储是永久的,只有在手动删除或者卸载浏览器的时候才会被清除;sessionStorage是会话,当窗口或页面被关闭的时候会被清除

输入一个url到页面渲染发生了什么

  1. 浏览器地址栏输入URL并回车
  2. 浏览器查找当前URL是否存在缓存,并比较缓存是否过期
  3. DNS解析URL对应ip
  4. 根据ip建立TCP连接
  5. 发送http请求
  6. 服务器处理请求,浏览器接收HTTP响应
  7. 浏览器解析并渲染页面
  8. 关闭TCP连接

 标准盒模型和怪异盒模型的区别,怎样转怪异盒模型

标准盒模型的组成:宽高(content) + padding + border + margin

怪异盒模型:width(content+border+padding)+margin

标准盒模型可以转成怪异盒模型:用属性box-sizing

box-sizing的属性有两个 border-box(怪异盒模型)/content-box(标准盒模型)

重绘和重排

重绘:元素的外观改变,列如元素的颜色和背景颜色发生改变

重排:重新排列元素,列如元素的尺寸,位置发生改变

JS篇

JS的数据类型

基本数据类型:

  1. Number
  2. String
  3. boolean
  4. undefined
  5. null
  6. symbol

引用数据类型:

  1. Object   对象
  2. Array  数组
  3. function   函数

 检测数据类型的方法

  • typeof检测基本数据类型
  • A  instanceof B 检测当前实例是否属于某各类

  • Object.prototype.toString.call()

setTimeout和setInterval定时器无法按时执行的原因

js是单线程,所以异步事件仅在空闲时才会被调用,代码执行异步事件时会按照将它们添加到队列的顺序执行,如果队列是空的,那么添加代码会立即执行,如果队列不是空的,那么就要等前面代码执行完在执行。

ES6新特性

  1. 新增块级作用域let定义变量和const定义常量。
  2. 变量的结构赋值。
  3. 模板字符串。
  4. 箭头函数。
  5. 扩展运算符。
  6. 模块(import/export)
  7. 类(class/extends)

new操作符具体做了什么

  1. 在内存创建一个新对象
  2. 把构造函数中的this指向新建的对象
  3. 会在新对象上添加一个__proto__属性,指向函数的原型对象prototype
  4. 判断函数返回值,如果值是引用数据类型就直接返回值,否则就返回this(新建对象)

this指向的各种情况

  1. 全局作用域中的函数,在非严格模式下this的指向是window
  2. 对象内部函数,其内部this指向对象本身
  3. 构造函数:其内部this指向生成的实例对象
  4. apply,call,bind改变的this的指向,其this指向第一个参数
  5. 箭头函数指向它的上级对象,

普通函数 箭头函数的区别

  1. 箭头函数没有原型 原型是undefined
  2. 箭头函数的this应该是创建时所在作用域指向的对象
  3. call,apply,bind方法改变不了箭头函数的指向

 

 

闭包的理解

产生的条件:

  1. 需要不销毁的函数,在函数当中return引用数据类型
  2. 嵌套的函数
  3. 内部函数要访问外部函数的变量

优点:

  • 延长变量的声明周期
  • 可以访问函数内部的变量

缺点:

  • 因为闭包里面的变量长期占用内存,容易导致低版本IE浏览器造成内存泄漏,当我们使用完闭包之后,需要手动释放(f = null)

什么是原型

所有函数都有一个prototype(显示原型对象)属性

所有对象都有一个__proto__(隐式原型对象)属性

所有内置函数都是function这个函数的实例对象

原型链

对象在访问某一个对象时,会在自身找,如果没有会在原型对象上找,一直往上查找,就会形成原型链(注意:如果找不到,最后是null)

call(),apply(),bind()的区别

  • call()的参数是直接放进去的,第二个参数之后的参数全部都用逗号分隔
  • apply()的所有参数都必须在一个数组传进去
  • bind()除了返回的是函数以外,它的参数和call()一样
  • 三者都可以改变this的指向对象
  • 三者第一个参数都是this要指向的对象,如果没有这个参数或参数为undefined或null时,默认指向全局变量window
  • 三者都可以传参,但是apply()是数组,而call()是参数列表,且apply()和call()是一次性传入参数,而bind()可以分为多次传入
  • bind()是返回绑定this之后的函数,便于稍后调用;apply()和call()是立即执行

Promise和async,await

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

特点:

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

作用:

  • 通常用来解决异步调用的问题
  • 解决回调地狱的问题
  • 提高代码的可读性,便于维护

async/await是基于Promise实现的,它不能用于普通的回调函数

async/await使得异步代码看起来像同步代码

async/await和Promise都是非阻塞的

async/await比Promise的优越性

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

 vue篇

什么是生命周期

vue实例有一个完整的生命周期,也就是从开始创建,初始化数据,编译模板,挂载DOM>渲染,更新>渲染,卸载等一系列过程称之为生命周期。

dom节点在那个生命周期生成

mounted生命周期

什么是指令

指令就是一套vue内置的模板,主要用于在视图节点上动态绑定变量,指令实际上也是DOM操作

自定义指令

在vue中,除了内置指令外,我们还可以使用vue.directive()或directives选项来自定义指令。

v-model的原理

在vue中v-model指令在表单input等元素上创建双向数据绑定,v-model本质上是一个语法糖,v-model在内部不同的元素使用不同的属性并抛出不同的事件

<input v-model="set" />
相当于
<input v-bind:value="set" v-on:input="set"=$event.target.value />

 vue响应式的原理

当vue组件被创建时,在生命周期的第一阶段(创建阶段)vue使用Object.defineProperty()对data选项进行遍历劫持并添加get/set钩子;在生命周期第二阶段(挂载阶段)指令与声明式变量touch时,会发生依赖收集,这时候再调用当前组件的watcher进行第一次Dom渲染,如果声明式变量发生变化时,vue会再次通知watcher更新视图。

理解vue的单向数据流

所有的props都使得其父子props之间形成了一个单向下行绑定:父级的更新会向下流动到子组件中,但是反过来不行,这样防止从子组件意外改变父组件的状态。

vue有哪些内置组件

插槽,动态组件,过渡动画,<component>

computed和watch的区别

computed是计算属性,依赖其它属性值,并且computed的值有缓存,只有它依赖的属性值发生改变,下次获取的属性值才会重新计算。

watch更多的是观察的作用,类似于某些数据的监听回调,每当监听的数据变化时都会执行回调

怎么理解组件化

组件化:把重复的代码提取出来封装成一个组件,实现组件的复用。

组件:组件就是HTML的一个扩展,使用粒度较小的HTML元素封装成组件

如何自定义组件

封装自定义组件的时候,可以使用vue选项属性,比如data,temolate,methods等

组件封装后,必须要组件注册才能在vue中使用,注册自定义组件时,组件名必须由多个单词用中划线连接

使用temolate选项指定组件的视图结构

如何进行组件注册

全局注册:使用Vue.component()进行全局注册,在任何组件中都可以使用

局部注册:使用components:{}进行局部注册,只有在当前组件作用域中使用。

注意:组件注册时,组件名称必须由多个单词用中划线连接

组件化的三大技术

自定义属性: <qf-score :num='num' count='1'></qf-score> 

自定义事件:  <qf-score @change='' @click=''></qf-score> 

自定义插槽: <qf-score> <div #default></div> </qf-score> 

组件的关系与通信

约定:在MVVM框架中,当我们谈论“组件”概念时,通常指的是自定义组件。当在A组件视图结构中使用到B组件,就会形成组件关系(父子关系),当组件足够多的时,组件之间就会形成“组件树”。

通信:在vue中通信就是组件之间的数据交互。父组件向子组件通信使用自定义属性,在子组件中使用props接收;子组件向父组件通信,使用自定义事件,在子组件中使用this.$emit(‘自定义事件’,‘数据’)回传数据。

什么是MVVM框架

MVVM流程:M数据层,VM虚拟DOM层,V视图层

MVVM的优点:低耦合,可重用性,独立开发

动态组件

被<keep-alive>所包裹的组件就是动态组件,并且这个组件是不会被销毁的,相当于是组件的一种缓存。

被动态组件包裹过的组件多了两个生命周期钩子activated(激活),deactivated(休眠)

activated和mounted的区别

activated可以执行多次,mounted只能执行一次。

deactivated和beforeDestroy的区别

deactivated可以执行多次,而beforeDestroy只能执行一次

什么是插槽

插槽就是子组件提供给父组件使用的一个占位符,用<slot></slot>表示,父组件可以在插槽中填充任何代码,填充的内容会替换子组件的<slot><slot/>标签。

什么是具名插槽

具名插槽就是给插槽取个名字,一个子组件可以放多个插槽,而父组件填充内容的时候可以根据名字把内容填充到对应的插槽中。

什么是作用域插槽

作用域插槽就是绑定数据的插槽,组件内变量绑定在上,使用v-slot指令,变量上就会绑定传递的属性和值。

组件中data为什么是一个函数,new Vue实例是一个对象

因为组件是用来复用的,且在js里的对象是引用关系,如果组件中的data是一个对象,那么作用域就没有隔离,子组件中的data属性值会互相影响,如果组件中的data是一个函数,那么每个实例都会返回一个对象,组件之间的data属性值不会互相影响;而new Vue的实例不会被复用的,所以不存在引用对象的问题

vue2和vue3的区别

  • 双向数据绑定发生变化:vue2双向数据绑定是利用ES5的object.defineProperty()对数据进行劫持,在结合发布订阅模式来实现的;vue3中使用ES6的ProxyAPI对数据代理
  • 根节点:vue2是单一根节点;vue3是多根节点。
  • API:vue2使用选项类型API(Options API),用属性来分割组件;vue3使用组合型API(Composition API),用方法来分割组件
  • 数据建立:vue2把数据放在data中;vue3使用setup方法,在组件初始化的时候vue触发
  • 生命钩子发生变化:
    vue2 vue3
    beforetCreate setup()
    created setup()
    beforeMount onBeforeMount
    mounted onMounted
    befoeUpdate onBeforeUpdate
    updated onUpdated
    beforeDestroy onBeforeUnmount
    destroyed onUnmounted
    activated onActivated
    deactivated onDeactivated
  • 传参不同:

    父传子:vue3通过props接收并通过toRefs转成响应式toRefs(props)

    子传父:在vue2中会调用到this.$emit然后传入事件名和参数对象,vue3中没用this,只能通过setup中的参数                                   传递。

  • vue3较vue2体积小,速度快
  • 在vue2中,主要使用的是观察者模式,不管数据多大,都会对数据进行创建检查;vue3对数据进行懒观察,仅对可见部分数据进行懒观察。

vue3里为什么要用Proxy替代defineProperty

defineProperty的弊端:

  • vue2是通过object.defineproperty中的getter和setter函数进行数据劫持完成数据响应的
  • 无法直接监听属性的改变
  • 无法直接监听数组

proxy的优势:

  • 作为vue3中替代defineProperty的API,相当于给一个对象的外层加了一层拦截,这层拦截可以对信息的过滤,修改。
  • 因为是在整个对象外层加了一层拦截,所以操作对象中的属性同时监听属性的变化
  • 可以直接监听数组变化

说一下nextTick是做什么的

nextTick()是将回调函数延迟在下一次Dom更新数据后调用,简单理解:当数据更新了,在dom中渲染后,自动执行该函数,next Tick多次调用会维持一个数组,之后会异步的把数组中的方法执行,这样就会在视图更新之后获取到真实的DOM元素。

nextTick和$nextTick的区别

  • nextTick():当数据发生变化,更新后执行回调,在下次DOM更新结束之后延迟回调,在修改数据之后立即执行这个方法,获取更新后的DOM
  • $nextTick():当DOM发生变化,更新后执行回调。将回调延迟到下次DOM更新之后执行。在修改数据立即使用它,然后等待DOM更新。
  • 区别:nextTick(callback)是全局的方法;$nextTick(callback)是回调的this自动绑定到调用它的实例上

SPA单页面的理解,它的优点缺点分别是什么

SPA0(single-page application)仅在Web页面初始化时加载响应的HTML,JS和CSS。一旦页面加载完成,SPA不会因为用户的操作而进行页面的重新加载和跳转;取而代之的是利用路由机制实现HTML内容的变化,UI与用户的交互,避免页面重新加载。

优点:

  • 用户体验好, 内容的改变不需要重新加载整个页面,避免了不必要的跳转和重复渲染
  • 基于上面一点,SPA相对对服务器压力小
  • 前后端分离,架构清晰,前端进行交互逻辑,后端负责数据处理

缺点:

  • 初次加载耗时多,为实现单页web应用功能及显示效果,需要统一加载,部分页面按需加载
  • SEO难度较大:由于所有的内容都在一个页面中动态显示,所以在SEO上有着天然的弱势

watch深度监听

deep:true开启深度监听

什么是导航守卫

在router实例对象上有三个重要的全局钩子(beforeEach、beforeResolve、afterEach),每次url发生变化时,都会触发这三个钩子按顺序执行。那么以后我可以在这些钩子编写验证逻辑,如果验证通过就放你过去,你就可以正常访问你想访问的页面;如果验证失败,就阻止你访问目标页面,这就实现“守卫”的效用了。在路由中,使用导航守卫和路由元信息,可以做鉴权、还可以做权限设计。

vue中父子组件传值,父组件异步请求,子组件不能实时更新怎么解决?(vue中数据不能实时更新怎么解决?)

原因:因为生命周期只会执行一次,数据要等到异步请求之后才能拿到,子组件的mounted钩子执行的时候,还没拿到父组件传过来的数据

解决方法:

  1. 初始还没拿到后端接口的异步数据的时候,不让组件渲染,等拿到的时候再去渲染组件。使用v-if="变量"去控制
  2. 使用watch监听数据的变化
  3. 使用Vuex

vuex和window的区别

 使用vuex保存数据和window保存数据原理一样,都是借助全局对象进行数据互通,不同的是vuex通过发布订阅机制将vue数据更新通知到所有订阅状态的组件上,实现数据更新,vuex和window单独使用的时候都会出现同一个问题,就是保存的数据再刷新页面,数据会丢失,出现这个问题是因为数据都是在运行内存保存的。

vuex中 mutations和action的区别

  • 主要区别在于mutations只能同步操作,action是异步操作,而且可以通过action提交mutations
  • mutations有个固有参数state,接收的是Vuex中的start对象
  • action也有一个固有参数context,但是context是state的父级,包含state,getters

 怎么封装axios

  1. 引入axios
  2. 创建一个实例
  3. 添加拦截器(请求拦截器,响应拦截器)
  4. 配置必传的参数
  5. 向外暴露
posted @   前端小二&沐沐  阅读(70)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示