前端面试理论基础

JS基础

js原型是什么

每个JavaScript对象(除了null和undefined)都有一个原型,可以通过Object.prototype访问到。原型本身也是一个对象,它可以包含属性和方法。当我们访问一个对象的属性或方法时,如果对象自身没有这个属性或方法,JavaScript会沿着原型链向上查找,直到找到对应的属性或方法或者到达原型链的顶端(即Object.prototype)。

原型和原型链是什么关系

在 JavaScript 中,每个对象都有一个原型(Prototype)。原型是一个对象,用于存储共享的属性和方法。当我们访问对象的属性或方法时,如果对象本身没有该属性或方法,JavaScript 引擎会沿着原型链向上查找,直到找到对应的属性或方法或者到达原型链的顶端。

原型链是由一系列对象连接而成的链表结构,通过每个对象的原型属性(__proto__)指向上一级对象的原型,最终指向 null。当我们访问一个对象的属性或方法时,如果对象本身没有,它会沿着原型链逐级向上查找,直到找到对应的属性或方法,或者到达原型链的顶端(即 null)。

简而言之,原型链是一种对象之间的连接关系,它通过原型属性将对象连接在一起,使得对象可以共享原型上的属性和方法。

可以使用 Object.getPrototypeOf() 方法获取一个对象的原型,使用 Object.prototype.isPrototypeOf() 方法来判断一个对象是否是另一个对象的原型。这些方法可以帮助我们理解和操作原型链。

需要注意的是,原型链是 JavaScript 语言中实现继承的一种机制。通过原型链,子对象可以继承父对象的属性和方法,并且可以在自己的原型上定义新的属性和方法。这种原型链的继承方式是 JavaScript 中的核心概念之一。

闭包


闭包是指在一个函数内部创建了另一个函数,并且内部函数可以访问外部函数的变量,即使外部函数执行完毕后,
内部函数依然可以访问和操作外部函数的变量。

闭包的特点:

内部函数可以访问外部函数的变量,包括参数和局部变量。
外部函数的变量在内部函数执行过程中保持在内存中,不会被垃圾回收机制回收。
内部函数可以访问外部函数创建时的上下文环境,即使外部函数执行完毕后,仍然可以访问。

闭包在JavaScript中有广泛的应用,常见的用途包括实现私有变量、保存函数状态和创建模块化的代码结构。使用闭包可以有效地保护和封装变量,防止其被外部访问和修改。同时,闭包也可以在函数执行完毕后继续操作状态和数据,实现更复杂的逻辑和功能。

需要注意的是,由于闭包会保留外部函数的作用域链,过度使用闭包可能会导致内存泄漏问题,因为闭包会持有对外部函数作用域的引用,导致内存无法被释放。因此,在使用闭包时需要注意合理使用,避免造成不必要的资源浪费。

promise用法

Promise是JavaScript中处理异步操作的一种机制,它提供了一种更优雅、可读性更高的方式来处理异步代码。
const myPromise = new Promise((resolve, reject) => {
  // 模拟异步操作
  setTimeout(() => {
    const randomNumber = Math.random();
    if (randomNumber < 0.5) {
      // 异步操作成功,调用resolve函数并传递结果
      resolve(randomNumber);
    } else {
      // 异步操作失败,调用reject函数并传递错误信息
      reject(new Error('操作失败'));
    }
  }, 1000);
});

async await


async/await 是 JavaScript 中处理异步操作的一种语法糖,它建立在 Promise 的基础之上,提供了一种更简洁、可读性更高的方式来编写异步代码。

async 关键字用于定义一个异步函数,它可以在函数体内使用 await 关键字来暂停函数的执行,等待一个 Promise 对象的状态变为 resolved(已完成)后再继续执行。

返回promise

在 JavaScript 中,可以通过创建和返回一个 Promise 对象来实现返回 Promise 的函数。
Promise 对象用于处理异步操作,并且可以在异步操作完成时,通过调用 resolve 方法将结果返回,或者通过调用 reject 方法将错误信息返回。

vue2和vue3的响应式原理分别是是什么


Vue 2 和 Vue 3 在响应式原理上存在一些区别。

Vue 2 的响应式原理基于 Object.defineProperty 方法实现。它通过递归地遍历对象的每个属性,在每个属性上定义 getter 和 setter。当属性被访问或修改时,会触发相应的 getter 和 setter 方法,从而实现对数据的响应式追踪和更新。

Vue 3 对响应式原理进行了重写,使用了 Proxy 对象作为代理。它在创建响应式对象时,通过创建一个与原始对象相关联的代理对象,拦截对代理对象的访问和修改操作。通过拦截操作,可以进行依赖追踪和触发更新,从而实现响应式的数据流动。

相较于 Vue 2 的响应式实现,Vue 3 使用 Proxy 对象具有以下优势:

更好的性能:Proxy 对象在拦截操作上比 Object.defineProperty 更高效,可以实现更快的响应式追踪和更新。
更好的兼容性:Proxy 对象是 ES6 的标准特性,支持的浏览器范围更广,而 Object.defineProperty 在某些旧版本浏览器中存在兼容性问题。
更强的功能:Proxy 对象提供了更多的拦截操作,可以对整个对象进行拦截,而不仅仅是属性级别的拦截。
需要注意的是,由于 Vue 3 在响应式原理上进行了重写,与 Vue 2 在一些语法和用法上存在一些差异,因此在迁移项目时需要留意响应式的实现方式的变化。

vue2和vue3的区别是什么,简洁描述一下

Vue 2 和 Vue 3 是两个不同版本的 Vue.js 前端框架,它们之间存在一些重要的区别。

响应式系统:Vue 2 使用 Object.defineProperty 实现响应式,而 Vue 3 使用 Proxy 对象实现响应式。Vue 3 的响应式系统性能更高,支持更复杂的数据类型,并且具有更好的 TypeScript 支持。

组合式 API:Vue 3 引入了组合式 API,使得组件的逻辑更加模块化和可复用。相比 Vue 2 的选项 API,组合式 API 提供了更清晰、更灵活的组件组织方式,使得开发更加简洁和可维护。

更好的性能:Vue 3 在编译器和运行时方面进行了优化,具有更小的包体积和更快的渲染速度。它采用了静态树提升、高效的 Diff 算法等优化策略,提升了应用的性能表现。

TypeScript 支持:Vue 3 对 TypeScript 的支持更加完善,并且内置了对 TypeScript 的类型推导和校验。这使得开发者在使用 TypeScript 编写 Vue 3 代码时能够获得更好的开发体验和类型安全。

更好的组件系统:Vue 3 引入了新的组件系统,包括 Teleport(原 Portals)、Suspense(原 Transition)、Fragments 等新特性,使得组件的开发更加灵活和强大。

总体而言,Vue 3 是对 Vue 2 的全面升级和改进,提供了更好的性能、更强大的功能和更好的开发体验。然而,由于 Vue 3 在一些语法和用法上与 Vue 2 存在一些差异,迁移项目时需要进行适当的调整和学习新的特性。

vue2生命周期


在Vue 2中,组件的生命周期钩子函数分为以下几个阶段:

创建阶段(Creation Phase):

beforeCreate:在实例被创建之前调用,此时无法访问到组件的数据和方法。
created:在实例创建完成后调用,可以访问到组件的数据和方法,但是此时模板还未渲染。
模板编译与挂载阶段(Template Compilation and Mounting Phase):

beforeMount:在模板编译和挂载之前调用,此时虚拟 DOM 已经生成,但尚未挂载到页面上。
mounted:在模板编译和挂载完成后调用,此时组件已经挂载到页面上,可以进行 DOM 操作和异步请求。
更新阶段(Update Phase):

beforeUpdate:在组件更新之前调用,此时虚拟 DOM 已经重新渲染,但尚未应用到页面上。
updated:在组件更新完成后调用,此时组件的数据已经更新,并且虚拟 DOM 已经应用到页面上。
销毁阶段(Destroy Phase):

beforeDestroy:在组件销毁之前调用,此时组件实例仍然可用,可以进行一些清理工作。
destroyed:在组件销毁后调用,此时组件实例已经被销毁,无法再访问组件的数据和方法。
在每个生命周期钩子函数中,你可以执行相应的操作,例如初始化数据、发送网络请求、操作 DOM 元素等。这些钩子函数提供了控制组件生命周期的灵活性和扩展性,使你可以在特定的阶段执行相应的逻辑。

需要注意的是,在Vue 2中,还存在一些过渡性的钩子函数(如beforeMount和mounted),用于支持 Vue 3 的迁移和兼容。在新的项目中,建议使用 Vue 3 的生命周期 API(Composition API)来编写组件逻辑。

vue3生命周期

在 Vue 3 中,生命周期钩子函数发生了变化。以下是 Vue 3 中常用的生命周期钩子函数:

beforeCreate: 在实例初始化之后、数据观测 (data observer) 和事件配置 (event/watcher setup) 之前被调用。
created: 在实例创建完成后被调用。可以访问到实例的数据、计算属性等。
beforeMount: 在挂载开始之前被调用。在此钩子函数中,模板已经编译完成,但尚未挂载到 DOM 中。
mounted: 在挂载完成后被调用。此时,实例已经被挂载到 DOM 中,并且可以访问到 DOM 元素。
beforeUpdate: 在数据更新之前被调用,发生在虚拟 DOM 重新渲染和打补丁之前。
updated: 在数据更新完成后被调用,发生在虚拟 DOM 重新渲染和打补丁之后。可以在此钩子函数中执行 DOM 操作,但要注意避免无限循环更新。
beforeUnmount: 在卸载组件之前被调用。可以进行一些清理操作,如清除定时器、解绑事件等。
unmounted: 在卸载组件之后被调用。此时,组件已经从 DOM 中移除。
需要注意的是,Vue 3 中移除了一些常用的生命周期钩子函数,如 beforeDestroy 和 destroyed。取而代之的是 beforeUnmount 和 unmounted。

另外,Vue 3 还引入了一个新的生命周期钩子函数 onRenderTracked 和 onRenderTriggered,用于在渲染时追踪和触发依赖项。

vue 使用ref获取组件内部的属性和方法有什么优点缺点

直接访问:通过 ref 可以直接访问组件内部的属性和方法,不需要通过组件实例的方式或者事件回调来进行访问。

简化代码:使用 ref 可以减少代码量,避免了繁琐的事件传递或者状态管理。

灵活性:ref 可以灵活地获取组件内部的任何属性和方法,包括私有属性和方法。

提高效率:直接访问组件内部属性和方法可以提高代码的执行效率,避免了不必要的中间操作。

然而,使用 ref 获取组件内部的属性和方法也有一些缺点:

违反封装性原则:通过 ref 直接访问组件内部的属性和方法可能违反组件的封装性原则,使组件的内部实现暴露给外部,增加了代码的耦合性。

难以追踪依赖关系:使用 ref 获取组件内部的属性和方法,父组件无法感知这些属性和方法的变化,难以追踪依赖关系,可能导致数据不一致或难以维护。

可能存在安全风险:直接访问组件内部的属性和方法可能存在安全风险,特别是当属性和方法涉及敏感数据或敏感操作时。

综上所述,使用 ref 获取组件内部的属性和方法可以提供便利,但在使用时应权衡利弊,确保在代码结构、可维护性和安全性方面取得平衡。在大多数情况下,推荐通过 props 和事件回调的方式进行组件间的通信和交互。只有在确实需要访问组件内部的特定属性和方法,并且明确了风险和后果的情况下,才考虑使用 ref 获取组件内部的内容。

echarts通用配置项

title: 设置图表标题的样式和内容。
tooltip: 配置鼠标悬停时的提示框样式和内容。
legend: 设置图例的样式和内容,用于显示数据系列的标识和名称。
xAxis 和 yAxis: 分别配置 x 轴和 y 轴的样式和刻度。
series: 配置数据系列的样式和数据源。
grid: 设置图表的绘图区域的位置和大小。
toolbox: 提供了一些工具按钮,如保存图表、切换显示数据等。
color: 定义图表的颜色主题。
backgroundColor: 设置图表的背景色。
animation: 配置图表的动画效果。
dataZoom: 设置数据区域缩放的样式和行为。
visualMap: 可视化映射,用于展示数据与颜色之间的关系。
series.itemStyle: 配置数据点的样式,如颜色、边框等。
series.label: 配置数据标签的样式,如显示位置、字体等。

vue的计算属性和监听有什么区别

用途不同:计算属性主要用于根据已有的数据衍生出新的数据,通常用于模板中展示或计算结果的获取;而监听则用于观察某个数据的变化并执行相应的操作,比如数据变化时触发异步操作或更新其他相关的数据。

语法不同:计算属性使用 computed 关键字定义,并返回一个计算结果;而监听使用 watch 关键字定义,并指定要监听的数据和对应的处理函数。

缓存机制不同:计算属性具有缓存机制,只有依赖的响应式数据发生变化时才会重新计算,其余情况下会返回缓存的计算结果,以提高性能;而监听没有缓存机制,每次监听的数据变化都会触发对应的处理函数。

使用场景不同:计算属性适用于对数据进行复杂的计算和转换,例如对数组进行过滤、排序、映射等操作;监听适用于监听数据的变化并执行相应的操作,例如监听输入框的值变化并发送请求。

vuex和pinia区别是什么

架构方式:Vuex 是基于 Vuex.Store 的单一全局状态树架构,将所有的状态集中存储在一个对象中。而 Pinia 是基于独立的 Store 类的分模块化架构,每个模块都有自己的状态、操作和 getter。

安装和使用方式:Vuex 是 Vue.js 官方推荐的状态管理库,在 Vue.js 项目中使用时,需要单独安装和配置。Pinia 是由 Vue Store Next 团队开发的新一代状态管理库,需要额外安装并通过插件方式集成到 Vue.js 项目中。

TypeScript 支持:Pinia 相比 Vuex 对 TypeScript 的支持更加友好,内置了 TypeScript 的类型声明,提供了更好的类型推断和类型安全。

API 设计:Pinia 提供了更简洁和直观的 API 设计,使用起来更加简单和易于理解。它采用了类似于 Vue 3 Composition API 的风格,可以使用类似 useStore() 的钩子函数来访问和使用状态。

性能优化:Pinia 在一些性能方面进行了优化,采用了更快的响应式机制和更新策略,可以提供更好的性能和响应性。

总的来说,Pinia 是一个相对较新的状态管理库,它提供了更模块化、直观和 TypeScript 友好的 API 设计,能够更好地与 Vue.js 3 和 TypeScript 项目集成。如果你的项目需要更好的 TypeScript 支持或更简单的 API 设计,可以考虑使用 Pinia。而对于较小的项目或对于 Vuex 已经熟悉且满足需求的项目,可以继续使用 Vuex。

vue2响应式原理

数据劫持:Vue 2 会遍历数据对象的每个属性,使用 Object.defineProperty 方法将属性转换为 getter 和 setter。当访问属性时,会触发 getter 函数,而修改属性时,会触发 setter 函数。

依赖追踪:Vue 2 中使用一个全局的 Dep 对象来存储依赖关系。每个被劫持的属性都会关联一个 Dep 对象。当属性的 getter 函数被调用时,会将当前正在计算的 Watcher(观察者)对象添加到 Dep 中,用于收集依赖关系。

数据更新:当被劫持的属性发生变化时,触发属性的 setter 函数。setter 函数会通知关联的 Dep 对象,然后 Dep 对象会通知所有收集的 Watcher 对象进行更新操作。

Watcher 和观察者模式:Watcher 是一个观察者对象,它负责订阅数据变化并执行相应的回调函数。Vue 2 中使用 Watcher 来收集依赖和更新视图。每个组件实例都会有对应的 Watcher 对象,当组件内使用了响应式数据时,会将 Watcher 添加到对应属性的 Dep 中,实现数据更新时的视图更新。

通过以上的响应式原理,Vue 2 能够实现数据和视图的自动关联,当数据发生变化时,视图会自动更新。这样开发者只需要关注数据的变化,无需手动更新视图,大大简化了开发过程。

vue3的 reactive、ref区别是什么

reactive 函数用于创建一个响应式的对象。它接收一个普通的 JavaScript 对象作为参数,并返回一个代理对象,该代理对象会监
ref 函数用于创建一个响应式的引用。它接收一个普通的 JavaScript 值作为参数,并返回一个包装对象,该包装对象包含一个名为 value 的属性,通过访问和修改 value 属性来实现响应式。
区别:
reactive 可以将一个普通的 JavaScript 对象转换为响应式对象,而 ref 只能用于创建响应式的引用。
reactive 返回的是一个代理对象,通过访问对象的属性来触发更新,而 ref 返回的是一个包装对象,通过访问 .value 属性来触发更新。
在模板中使用时,可以直接使用 ref 创建的响应式引用,而使用 reactive 创建的响应式对象需要使用解构或者直接访问对象的属性来获取和更新值。

你可能感兴趣的:(前端,面试,职场和发展)