前端面试题记录

这里写目录标题

1、JS 数据类型有哪些?

JavaScript 中的数据类型包括:

  1. 基本数据类型:Number、String、Boolean、Null、Undefined、Symbol(ES6 新增)。

  2. 引用数据类型:Object(包括 Array、Function、Date、RegExp 等)。

2、判断一个值是什么类型有哪些方法?

在大多数编程语言中,判断一个值的类型有以下几种方法:

  1. typeof 操作符:typeof 操作符可以返回一个值的数据类型,例如 typeof 123 返回 “number”,typeof “hello” 返回 “string”。

  2. instanceof 操作符:instanceof 操作符可以判断一个对象是否是某个类的实例,例如 obj instanceof Array 判断 obj 是否是 Array 类的实例。

  3. Object.prototype.toString.call() 方法:这个方法可以返回一个值的类型,例如 Object.prototype.toString.call(123) 返回 “[object Number]”,Object.prototype.toString.call(“hello”) 返回 “[object String]”。

  4. typeof 和 instanceof 操作符的局限性:typeof 操作符不能判断 null 和数组类型,而 instanceof 操作符不能判断基本数据类型。因此,可以使用 Object.prototype.toString.call() 方法来判断一个值的类型,这个方法可以判断所有类型的值。

3、null 和 undefined 的区别

首先 Undefined 和 Null 都是基本数据类型,这两个基本数据类型分别都只有一个值,就是 undefined 和 null。

undefined 代表的含义是未定义,null 代表的含义是空对象。一般变量声明了但还没有定义的时候会返回 undefined,null主要用于赋值给一些可能会返回对象的变量,作为初始化。


  • undefined 表示不存在这个值。
  • undefined :是一个表示"无"的原始值或者说表示"缺少值",就是此处应该有一个值,但是还没有定义。当尝试读取时会返回 undefined
  • 例如变量被声明了,但没有赋值时,就等于undefined
  • null 表示一个对象被定义了,值为“空值”
  • null : 是一个对象(空对象, 没有任何属性和方法)
  • 例如作为函数的参数,表示该函数的参数不是对象;
  • 在验证null时,一定要使用 === ,因为 ==无法分别null 和 undefined

4、怎么判断一个变量arr的话是否为数组(此题用 typeof 不行)

  • 用instanceof :arr instanceof Array
  • 用constructor:arr.constructor == Array
  • 用object.protype.toString:Object.protype.toString.call(arr) == ‘[Object Array]’

5、bind、call、apply 区别?如何实现一个bind?

  • 三者都可以改变函数的 this 对象指向
  • 三者第一个参数都是 this 要指向的对象,如果如果没有这个参数或参数为 undefined 或 nu11,则默认指向全局 window
  • 三者都可以传参,但是 apply 是数组,而 cal1 是参数列表,且 apply 和 ca1 是一次性传入参数,而 bind可以分为多次传入
  • bind 是返回绑定this之后的函数, apply 、 call 则是立即执行

6、什么是防抖和节流?有什么区别?如何实现?

什么是防抖和节流:

防抖:在用户多次触发事件,当用户停止触发事件,将事件执行一次。等待一段时间。
节流:在用户多次触发事件,会在多次触发的过程中,间隔执行事件。按照一定的频率执行。

区别:

相同点:

都可以通过setTimeOut实现,目的都是降低回调执行效率,节省计算资源

不同点:

函数防抖,在一段连续操作结束后,处理回调,利用clearTimeOut和setTimeOut实现。

函数节流,在一段连续操作中,每一段时间只执行一次,频率较高的事件中使用来提高性能。

函数防抖关注一定时间连续触发的事件,只在最后执行一次,而函数节流一段时间内只执行一次。

7、怎么理解回流跟重绘?什么场景下会触发?

对回流和重绘的理解:

**回流(reflow)重绘(repaint)**是浏览器渲染页面时的两个重要概念。

回流指的是当页面中的元素发生位置、大小等属性的变化时,浏览器需要重新计算元素的位置和大小,然后重新布局整个页面,这个过程就是回流。回流会导致页面的重新渲染,因此会比重绘更加耗费性能。

重绘指的是当页面中的元素的样式发生变化时,浏览器只需要重新绘制这些元素的样式,而不需要重新计算元素的位置和大小,这个过程就是重绘。重绘不会导致页面的重新布局,因此比回流的性能消耗要小。

在什么场景下会触发回流?

  • 页面首次渲染时; -
  • 浏览器窗口大小发生变化时;
  • 元素的位置、大小、内容发生变化时;
  • 元素的样式发生变化时;
  • 获取某些属性(如 offsetTop、offsetLeft、offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight)时。

在什么场景下会触发重绘?

  • 元素的样式发生变化时;
  • 元素的背景色、文本颜色、边框颜色等颜色属性发生变化时;
  • 元素的不透明度发生变化时。

因此,在开发过程中,我们应该尽量避免频繁触发回流和重绘,可以采取以下措施:

  • 尽量减少 DOM 操作;
  • 将需要多次操作的 DOM 元素缓存起来,避免重复获取;
  • 将需要多次操作的样式集中在一起,避免多次触发重绘;
  • 使用 CSS3 动画代替 JavaScript 动画,因为 CSS3 动画可以利用硬件加速,性能更好;
  • 使用虚拟列表等技术,避免一次性渲染大量数据。

8、vue路由的原理?

vue路由的两种模式:hash模式histroy模式

hash路由

在正常路径后跟一个 # 号,匹配 # 后边的路径为前端路由,通过window.onhashchange方法来操控路由改变的时候切换内容

onhashchange 方法的触发时机

  • 通过改变location.href或location.hash的值;
  • 直接更改浏览器地址,在最后面增加或改变#hash;
  • 通过触发点击带锚点的链接;
  • 浏览器前进后退可能导致hash的变化,前提是两个网页地址中的hash值不同。

histroy路由模式

在window.history这个对象中,包含浏览器的历史,而在HTML5中,新增了 history.pushState和history.replaceState,通过这两个API可以改变url地址且不会发送请求,同时还有window.onpopstate事件,实现原理与hash相似,只不过因为没有了 # 号,所以刷新页面还是会向服务器发送请求,而后端没有对应的处理措施的话,会返回404,所以需要后端配合

window.onpopstate事件的触发时机

仅仅调用pushState方法或replaceState方法 ,并不会触发该事件;
只有用户点击浏览器倒退按钮和前进按钮,或者使用JavaScript调用back、forward、go方法时才会触发。
另外,该事件只针对同一个文档,如果浏览历史的切换,导致加载不同的文档,该事件也不会触发。

9、你了解vue的diff算法吗?说说看?

Vue的diff算法是一种高效的虚拟DOM更新算法,用于比较新旧虚拟DOM树的差异,并最小化DOM操作的次数,从而提高性能。 它能够在更新DOM时,只更新需要更新的部分,而不是重新渲染整个DOM树。

Vue的diff算法采用了双端比较的策略,即同时从新旧虚拟DOM树的两端开始比较,直到遇到第一个不同的节点为止。这种策略可以最大程度地减少比较次数,提高比较效率。

在比较过程中,Vue会对节点进行四种类型的比较:

  1. 新节点不存在,旧节点存在:将旧节点删除
  2. 新节点存在,旧节点不存在:将新节点插入
  3. 新节点和旧节点都存在,但是节点类型不同:将旧节点删除,插入新节点
  4. 新节点和旧节点都存在,且节点类型相同:比较节点的属性和子节点,更新差异部分 在比较完成后,Vue会根据差异部分生成一组最小化的DOM操作指令,然后批量执行这些指令,从而更新真实的DOM树。

Vue的diff算法主要分为两个阶段:

  1. 树的遍历阶段:在这个阶段中,Vue会递归遍历新旧虚拟DOM树,找出需要更新的节点。
  2. 节点比较阶段:在这个阶段中,Vue会比较新旧虚拟DOM节点,找出需要更新的节点,并将这些节点标记为需要更新。

在树的遍历阶段中,Vue会对新旧虚拟DOM树进行深度优先遍历,对于每个节点,Vue会给它打上一个唯一的标识符,这个标识符可以用来判断新旧节点是否相同。如果新旧节点相同,Vue会将它们的标识符保存下来,以便在节点比较阶段中使用。

在节点比较阶段中,Vue会比较新旧节点的标识符,如果它们相同,Vue会进一步比较它们的属性和子节点。如果它们的属性和子节点都相同,Vue会认为它们是相同的节点,不需要更新。如果它们的属性或子节点有任何一个不同,Vue会将它们标记为需要更新,并将它们的新属性和子节点应用到真实的DOM节点上。

总的来说,Vue的diff算法是一种高效的虚拟DOM更新算法,可以最小化DOM操作的次数,提高性能。

10、Vue3.0的设计目标是什么?做了哪些优化?

设计目标

  • 更小
    Vue3移除一些不常用的 API
  • 更快
    diff算法优化
    静态提升
    事件监听缓存
    SSR优化
  • TypeScript支持
  • API设计一致性
  • 提高自身可维护性
  • 开放更多底层功能
    vue3在兼顾vue2的options API的同时还推出了composition API,大大增加了代码的逻辑组织和代码复用能力

优化

源码
* 源码管理
vue3整个源码是通过 monorepo的方式维护的,根据功能将不同的模块拆分到packages目录下面不同的子目录中
* TypeScript
Vue3是基于typeScript编写的,提供了更好的类型检查,能支持复杂的类型推导
性能
* 体积优化
* 编译优化
* 数据劫持优化
语法 API
* 优化逻辑组织
* 优化逻辑复用

  • Vue3的最大设计目标是替代Vue2,为了实现这一点,Vue3在以下几个方面做了很大改进,如:易用性、框架性能、扩展性、可维护性、开发体验等
  • 易用性方面主要是API简化,比如v-model在Vue3中变成了Vue2中v-model和sync修饰符的结合体,用户不用区分两者不同,也不用选择困难。类似的简化还有用于渲染函数内部生成VNode的h(type,props, children),其中props不用考虑区分属性、特性、事件等,框架替我们判断,易用性大增。
  • 开发体验方面,新组件Teleport传送门、Fragments 、Suspense等都会简化特定场景的代码编写,SFC Composition API语法糖更是极大提升我们开发体验。
  • 扩展性方面提升如独立的reactivity模块,custom renderer API等
  • 可维护性方面主要是Composition API,更容易编写高复用性的业务逻辑。还有对TypeScript支持的提升。
  • 性能方面的改进也很显著,例如编译期优化、基于Proxy的响应式系统

11、Vue3.0 所采用的 Composition Api 与 Vue2.x 使用的 Options Api 有什么不同?

在使用vue2进行开发的时候会遇到,代码的可读性随着组件的变大而便差,每一种代码复用的方式,都存在缺点,TypeScript支持有限,而这些问题vue3却可以迎刃而解

options API

选项API,即以.vue为后缀的文件,通过定义methodscomputedwatchdata等属性和方法,共同处理页面的逻辑,这种选项式的写法,如data中定义状态,methods中定义方法,然而这种情况随着组件复杂,导致对应的属性的列表也会增长,这可能会导致组件难以阅读

Compositions Api

在vue3中Compositions Api中,组件根据逻辑功能来组织的,一个功能所定义的所有Api会放在一起,更加高内聚,低耦合

对比

从逻辑组织和逻辑复用两个方面比较Compositions Api和options Api

逻辑组织
在选项式Api写法中随着组件的内容变得复杂,状态和方法的分离,使得理解和维护组件变得异常困难,并且选项分离也掩盖了组件的内层逻辑

在组合式Api的写法中属性和方法可以写在一起,在进行修改的时候可以非常的明了

逻辑复用
在选项式Api中进行逻辑复用的时候会出现命名冲突和数据来源不清晰的问题

总结

  • 在逻辑组织和逻辑复用方面,组合式Api优于选项式Api
  • 因为组合式Api几乎都是函数,会有更好的逻辑判断
  • 组合式Api对tree-shaking友好,代码也更容易压缩
  • 组合式Api中见不到this的使用,减少了this指向不明的问题

12、说说 React 生命周期有哪些不同阶段?每个阶段对应的方法是?

阶段

react生命周期分为旧生命周期新生命周期他们的阶段都分为:
挂载阶段
更新阶段
卸载阶段

旧生命周期

挂载阶段

constructor:实例过程中自动调用的方法

componentWillMount:挂载前

render:渲染

componentDidMount:挂载完成

更新阶段

componentWilReceiveProps:当子组件接收父组件传过来的props,会执行这个函数

shouIdComponentUpdate:当更新state值的时候会执行这个函数

componentWillUpdate:执行render前的函数,里面有两个参数是将要更新的state和props的值

render:渲染

componentDidUpdate:更新完毕

卸载阶段

componentWillUnmount:卸载阶段

新生命周期

挂载阶段

coustructor:实例过程中自动调用的方法

getDerivedStateFromProps:组件创建和更新阶段,不论是props变化还是state变化,也会调用,在每次render方法前调用,第一个参数为即将更新的props,第二个参数为上一个状态的state,可以比较props 和 state来加一些限制条件,防止无用的state更新,该方法需要返回一个新的对象作为新的state或者返回null表示state状态不需要更新

render:渲染

componentDidMount:挂载完成

更新阶段

getDerivedStateFromProps:同上

shouIdcomponentUpdate:到新的props或者state时都会调用,通过返回true或者false告知组件更新与否,一般情况,不建议在该周期方法中进行深层比较,会影响效率
,同时也不能调用setState,否则会导致无限循环调用更新

render:渲染

getSnapshotBeforeUpdate:执行之时DOM元素还没有被更新方法返回的一个Snapshot值,作为componentDidUpdate第三个参数传入,此方法的目的在于获取组件更新前的一些信息

componentDidUpdate:更新完成之后

卸载阶段
componentWillUnMount:卸载

新旧生命周期的区别

在新的生命周期中,react弃用了componentWillMount、componentWillReceiveProps、componentWillUpdate这三个钩子,取而代之的是getDerivedStateFromProps,其实就是把那三个钩子的含义融入到了这一个钩子中,写法如下:
另外还新增了一个钩子,getSnapshotBeforeUpdate,这里可获取到即将要更新的props和state
其他和原来的生命周期一致。

13、如何解决跨域问题?

跨域主要是因为同源策略引起的,这是浏览器的一种安全机制,即协议,端口,域名都相同

解决跨域的方法

  • **JSONP:**通过script标签的src属性实现,因此JSONP方案只支持get请求,并且兼容性好,几乎所有浏览器都支持
  • **CORS:**通过服务器设置一系列响应头来实现跨域,而客户端不需要做什么事
  • **代理转发:**在前端服务和后端接口服务之间架设一个中间代理服务,它的地址保持和前端服务一致,
    • 代理服务和前端服务之间由于协议域名端口三者统一不存在跨域问题,可以直接发送请求
    • 代理服务和后端服务之间由于并不经过浏览器没有同源策略的限制,可以直接发送请求
  • **Nginx反向代理:**反向代理和代理很像,都是在客户端与服务端中间架设一个中间代理服务器,不同点在于代理是代表客户端向服务端发送请求,反向代理是代表服务端接收客户端发送的请求

14、如何优化webpack打包速度?

的打包速度影响着我们的开发体验和及时构建,所有我们需要提高webpack的打包速度

方法: ll

  • 减少文件的搜索范围
    在实际开发中,我们会在项目中引入大量的第三方库,以及我们也会进行模块的引用,这样,会导致webpack在寻找文件的过程中占用大量的时间,而我们就需要减少文件的搜索范围,方法:有配置resolve.models,在这里配置模块库的位置(node_models)从而减少搜索范围,这是webpack2以上版本的写法,设置text&include&exclude,webpack的loaders允许每个子项有一下属性test(必须满足的条件),include(导入的文件将有加载程序转换的路径或文件数组),exclude(不能满足的条件)
  • 增强代码压缩工具
    webpack提供的UglifyJS插件,采用单线程压缩,速度很慢,可以使用webpack-parallel-uglify-plugin插件,可以并行运行UglifyJS插件,更加充分合理的使用CPU资源,大大减少构建时间
  • 使用Happypack来加速代码的构建
    将原有的 webpack 对 loader 的执行过程,从单一进程的形式扩展多进程模式
  • 设置 babel 的 cacheDirectory 为true,将文件进行缓存
  • 设置noParse
    如果你确定一个模块中,没有其它新的依赖,就可以配置这项, Webpack 将不再扫描这个文件中的依赖,这对于比较大型类库,将能促进性能表现
  • 拷贝静态文件,将指定的文件拷贝到指定的目录下

15、SPA首屏加载速度慢的怎么解决?

首屏时间,指的是浏览器从响应用户输入网址地址,到首屏内容渲染完成的时间,此时整个网页不一定要全部渲染完成,但需要展示当前视窗需要的内容。
加载慢的原因

  • 网络延时问题
  • 资源文件体积是否过大
  • 资源是否重复发送请求去加载了
  • 加载脚本的时候,渲染内容堵塞了

解决方案:

  • 减小入口文件积
  • 静态资源本地缓存
  • UI框架按需加载
  • 图片资源的压缩
  • 组件重复打包
  • 开启GZip压缩
  • 使用SSR

16、new操作符具体干了什么?

  • 创建一个空对象,并且 this 变量引用该对象,同时还继承了该函数的原型
  • 属性和方法被加入到 this 引用的对象中
  • 新创建的对象由 this 所引用,并且最后隐式的返回 this

一种创建对象的方法,使用new关键字来创建一个拥有独立内存区域指向原型的指针的对象。当我们使用new的时候,js解析器会分配一块内存空间,用以存放当前的对象的自有属性。之后解析器会给这一对象一个_proto_属性指向的原型对象内容。

构造函数

用new关键字来调用的函数,首字母一般大写,构造函数会有一个属性prototype一个原型对象prototype,prototype的构造函数constructor指向该函数

用new生成的实例有一个proto指向该函数的prototype原型对象

(1) 创建一个新对象;
(2) 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象) ;
(3) 执行构造函数中的代码(为这个新对象添加属性) ;
(4) 返回新对象

17、说说你对闭包的理解?闭包使用场景?

什么是闭包?

函数执行后返回结果是一个内部函数,并被外部变量所引用,如果内部函数持有被执行函数作用域的变量,即形成了闭包。

可以在内部函数访问到外部函数作用域。

使用闭包,一可以读取函数中的变量,二可以将函数中的变量存储在内存中,保护变量不被污染。

因为闭包会把函数中的变量存储在内存中,会对内存有消耗,所以不能滥用闭包,否则会影响网页性能,造成内存泄漏。当不需要使用闭包时,要及时释放内存,可将内存函数对象的变量赋值为null。

闭包的优点?

  1. 避免全局变量的污染

  2. 把变量存在独立的作用域,作为私有成员存在

  3. 可以在内存中维护一个变量

  4. 能够读取函数内部的变量

闭包的缺点?

  1. 闭包会常驻内存,会增大内存使用量,会造成内存泄漏
  2. 可能会获取到意外的值

闭包应用场景?

  1. 创建私有变量和延长变量的生命周期

  2. setTimeOut传参

  3. 回调

  4. 封装变量

  5. 为节点循环绑定click事件

  6. 柯里化函数

18、说说JavaScript中的数据类型?存储上的差别?

  • 基本数据类型存储在栈中
    1. Number:整型(十进制,八进制,二级制)和浮点类型和NAN操作失败
    2. Undefined:当使用 var或 let声明了变量但没有初始化时,就相当于给变量赋予了  undefined值
    3. String:字符串可以使用双引号(")、单引号(')或反引号(`)表示,并且字符串不可变
    4. Null:null表示一个空对象指针,这也是typeof传一个null会返回object,undefined是由null派生的
    5. Boolean:Boolean类型有两个值true和false,通过Boolean可以将其他值变成Boolean
    6. Symbol:Symbol (符号)是原始值,且符号实例是唯一、不可变的。符号的用途是确保对象属性使用唯一标识符,不会发生属性冲突的危险
    
  • 复杂数据类型存储在堆中
    7. Object:创建object常用方式为对象字面量表示法,属性名可以是字符串或数值
    8. Array:js数组是一组有序的数据,但跟其他语言不同的是,数组可以存储任意数据类型,并且数组的大小,也是根据数据的变化而动态变化的
    9. Function:函数实际上是一个对象,每个函数都是Function的实例,而Function也有属性和方法,跟其他引用类型一样
    
  • 声明变量时不同的内存地址分配
    • 简单类型的值存放在栈中,在栈中存放的是对应的值
    • 复杂数据类型存放在堆中,在堆中存放的是执行内存的地址
  • 不同类型数据导致赋值变量时的不同:
    • 简单数据类型赋值,是生成相同的数据,两个对象对应不同的地址
    • 复杂数据类型赋值,是将保存对象的内存地址赋值给另一个变量,也就是两个变量指向堆内存中的同一个对象

19、说说你对BOM的理解,常见的BOM对象你了解哪些?

DOM就是我们的文档对象,也就是HTML元素等

BOM则是浏览器对象模型,提供了独立于内容与浏览器窗口进行交互的对象。其实BOM就是利用JavaScript开发web应用的核心,它提供给我们可以操作浏览器的一些功能对象。

作用就是跟浏览器做一些交互,比如如何进行页面的后退、前进、刷新,浏览器的窗口发生变化,滚动条的滚动,以及获取客户的一些信息。如:浏览器品牌版本,屏幕分辨率。

浏览器的全部内容可以看成DOM,整个浏览器可以看成BOM

DOM和BOW的区别:

DOM

  • 是文档对象模型
  • DOM就是把文档当做一个对象来看待
  • DOM的顶级对象是document
  • DOM主要学习是操作页面元素
  • DOM是WSC标准规范

BOM

  • 是浏览器对象模型
  • BOM就是把浏览器当做一个对象来看待
  • BOM的顶级对象是window
  • BOM学习的是浏览器窗口交互的一些对象
  • BOM是浏览器厂商在各自的浏览器定义的,兼容性较差

Bom的核心对象是window,它表示浏览器的一个实例

在浏览器中,window对象有双重角色,即是浏览器窗口的一个接口,又是全局对象

因此所有在全局作用域中声明的变量、函数都会变成window对象的属性和方法

常见的BOM对象都有哪些?

  • window对象:是js最顶层对象
  • document对象:文档对象
  • location对象:浏览器当前URL信息
  • navigator对象:浏览器本身信息
  • screen对象:客户端屏幕信息
  • history对象:浏览器返回历史信息

20、说说你对promise的了解?

Promise是ES6中的新增的异步处理方法,主要是用于解决ES5中使用回调函数产生的地狱回调的问题

Promise有三种状态,pedding准备中,fullfiilled已完成, rejected失败,状态只能有准备中=>已完成 或 准备中=>失败

参数两个: resolve和reject 执行resolve参数方法会调用then方法,执行reject参数方法调用catch方法。

then方法执行成功后调用的方法
catch方法执行失败调用的方法
all() 参数是个数组,执行多个Promise对象,必须所有的对象状态执行完后才会变成已完成的状态
race()方法 执行多个Promise对象,只要有一个对象状态是已完成,对象的状态就是已完成。

promise`是es6新增的异步处理函数,主要是为了解决回调函数产生的地狱回调问题,是一种链式回调问题

Promise简单来说就是一个容器,里面保存这未来才会结束的事件的结果

promise是一个对象,从它里面可以获取异步操作的最终状态(成功或失败)

Promise是一个构造函数,对外提供统一的API,自己身上有all,reject ,resolve等方法,原型上有thencatch等方法

Promise是ES6中的新增的异步处理方法,主要是用于解决ES5中使用回调函数产生的地狱回调的问题
Promise有三种状态,pedding准备中,fullfiilled已完成, rejected失败,状态只能有准备中=>已完成 或 准备中=>失败

特点

Promise对象的状态不受外界状态的影响
一旦状态改变,就不会再变,任何时候都可以得到这个结果

promise的状态

promise有三种状态

  • pending 初始状态
  • fulfilled 成功状态
  • rejected 失败状态

Promise接收一个函数作为参数,该函数有两个参数分别是resolverejected
resolve函数的作用:在异步操作成功时将参数传递出去
reject函数的作用:异步操作失败将参数传递出去

promise的方法
then:异步操作执行成功后执行
catch:异步操作失败后执行
all() 参数是个数组,执行多个Promise对象,必须所有的对象状态执行完后才会变成已完成的状态
race()方法 执行多个Promise对象,只要有一个对象状态是已完成,对象的状态就是已完成

21、说说webpack中常见的Plugin?解决了什么问题?

plugin赋予webpack各种灵活的功能,例如打包优化、资源管理、环境变量注入等,它们会运行在 webpack 的不同阶段(钩子 / 生命周期),贯穿了webpack整个编译周期

Webpack 中常见的 Plugin 有很多,以下是一些常用的 Plugin:

  1. HtmlWebpackPlugin:自动生成 HTML 文件,并将打包后的 JS 文件自动引入到 HTML 文件中,方便开发和部署。

  2. MiniCssExtractPlugin:将 CSS 从 JS 文件中提取出来,生成单独的 CSS 文件,减小 JS 文件的大小,提高页面加载速度。

  3. CleanWebpackPlugin:在每次打包前清除旧的打包文件,避免文件冗余。删除(清理)构建目录

  4. DefinePlugin:定义全局变量,方便在代码中使用,例如定义环境变量、API 地址等。

  5. HotModuleReplacementPlugin:热更新插件,可以在不刷新页面的情况下更新页面内容,提高开发效率。

  6. UglifyJsPlugin:压缩 JS 代码,减小文件大小,提高页面加载速度。

  7. CopyWebpackPlugin:将文件或文件夹复制到打包后的目录中,例如复制图片、字体等静态资源。

这些 Plugin 解决了很多开发中的问题,例如自动化生成 HTML 文件、提取 CSS 文件、清除旧的打包文件、定义全局变量、热更新、压缩代码、复制静态资源等。这些问题如果手动处理,会增加开发成本和出错的概率,使用 Plugin 可以提高开发效率和代码质量。

22、说说你对作用域链的理解?

  • 作用域链的作用是保证执行环境里有权访问的变量和函数是有序的,作用域链的变量只能向上访问,变量访问到window对象即被终止,作用域链向下访问变量是不被允许的
  • 简单的说,作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。

作用域,即变量(变量作用域又称上下文)和函数生效(能被访问)的区域或集合

作用域分类:全局作用域,函数作用域,块级作用域

全局作用域

任何不在函数或大括号内声明的变量,都在全局作用域下,全局声明的变量可以在程序的任何位置访问

函数作用域

函数作用域也就局部作用域,如果一个变量声明在函数内部,那么这个变量就只能在函数内部访问到

块级作用域

es6中新增letconst关键字,和var关键字不同,在大括号内使用letconst声明的变量存在块级作用域中,在大括号外不能访问这些变量

词法作用域

词法作用域又称静态作用域,变量被创建是就确定好了,而非执行阶段确定的,js就是词法作用域

作用域链

当在javascript中使用一个变量的时候,首先js引擎会尝试在当前作用域下去寻找该变量,如果没有找到,在到他的上层作用域中去寻找,以此类推直到找到该变量或是已经到了全局作用域下,如果全局作用域下仍然找不到该变量,他就会在全局范围内隐式声明该变量(非严格模式下)或是直接报错。

23、说说 React中的setState执行机制?

一个组件的显示形态可以由数据状态和外部参数所决定,而数据状态就是state,当需要修改里面的值的状态需要通过调用setState来进行改变,从而达到更新组件数据的作用;

SetState第一个参数可以是一个对象,或者是一个函数,而第二个参数就是一个回调函数

用于可以实时的获取更新之后的数据;

在使用setState更新数据的时候,setState分为同步更新和异步更新,在组件生命周期或react合成事件中,setState是异步的;在setTimeout或者原生dom事件中,setState是同步的

总结就是对同一个值进行多次setState,setState的批量更新策略就会对其进行覆盖,取最后一次的执行结果。

24、Vue组件之间的通信方式都有哪些?

父子组件之间的通信
兄弟组件之间的通信
祖孙与后代组件之间的通信
非关系组件间之间的通信

通信方式

  • 通过 props 传递
    适用场景:父组件传递数据给子组件
    子组件设置props属性,定义接收父组件传递过来的参数
    父组件在使用子组件标签中通过字面量来传递值
  • 通过 $emit 触发自定义事件
    适用场景:子组件传递数据给父组件
    子组件通过触发自定义事件,emit第二个参数为传递的数值
    父组件绑定监听器获取到子组件传递过来的参数
  • 使用ref
    父组件在使用子组件的时候设置ref
    父组件通过设置子组件ref来获取数据
  • EventBus
    使用场景:兄弟组件传值
    创建一个中央事件总线EventBus
    兄弟组件通过 e m i t 触发自定义事件, emit触发自定义事件, emit触发自定义事件,emit 第二个参数为传递的数值
    另一个兄弟组件通过$on监听自定义事件
  • $parent$root
    通过共同祖辈$parent或者$root搭建通信桥连
  • attrslisteners
    适用场景:祖先传递数据给子孙
    设置批量向下传属性$attrs和 l i s t e n e r s 包含了父级作用域中不作为 p r o p 被识别 ( 且获取 ) 的特性绑定 ( c l a s s 和 s t y l e 除外 ) 。可以通过 v − b i n d = " listeners 包含了父级作用域中不作为 prop 被识别 (且获取) 的特性绑定 ( class 和 style 除外)。 可以通过 v-bind=" listeners包含了父级作用域中不作为prop被识别(且获取)的特性绑定(classstyle除外)。可以通过vbind="attrs" 传⼊内部组件
  • ProvideInject
    在祖先组件定义provide属性,返回传递的值
    在后代组件通过inject接收组件传递过来的值
  • Vuex
    适用场景: 复杂关系的组件数据传递
    Vuex作用相当于一个用来存储共享变量的容器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夏兮颜☆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值