当前位置:网站首页 > Node.js开发 > 正文

node 面试(node面试题整理简书)



js

1. 函数式编程

计算过程视为一系列的函数调用,函数的输出完全由输入决定,不依赖于或改变程序的状态,使得函数式编程的代码更加可预测和易于理解。

函数式编程的三个核心概念:纯函数、高阶函数和柯里化。

高阶函数:函数可以作为参数传递给其他函数,也可以作为其他函数的返回值。
纯函数:相同的输入总是得到相同的输出,函数不改变外部状态,也不依赖外部状态,不产生副作用。
柯里化:它可以将一个接受多个参数的函数转换为一系列使用一个参数的函数。提高了函数的复用性和模块性

2. 不可变数据的优势

1、易于追踪变化: 当数据不可变时,每次变化都会生成新的数据对象,更容易跟踪和理解数据的变化过程。
2、性能优化: React可以通过比较新旧数据对象,确定何时进行渲染,从而提升性能。
3、避免副作用: 直接修改数据可能导致副作用和难以预料的错误。不可变数据可以减少这些问题。
4、时间旅行调试: 使用不可变数据,可以更轻松地实现时间旅行调试,即查看应用在不同时间点的状态。


3. 闭包

更详细内容: https://blog.csdn.net/_/article/details/
闭包是指一个函数可以访问它定义时所在的词法作用域以及全局作用域中的变量。当通过调用外部函数返回的内部函数后,即使外部函数已经执行结束了,但是被内部函数引用的外部函数的变量依然会保存在内存中,我们把引用了其他函数作用域变量的函数和这些被引用变量的集合,称为闭包(Closure)。
这种函数嵌套和变量共享的方式就是闭包的核心概念。当一个函数返回另一个函数时,它实际上返回了一个闭包,其中包含了原函数定义时的词法作用域和相关变量。
应用: 封装私有变量,做缓存,模块化编程。防抖,节流,函数柯里化
缺点: 由于闭包会引用外部函数的变量,但是这些变量在外部函数执行完毕后没有被释放,会一直存在于内存中,造成了内存泄漏。
1.及时释放闭包:手动调用闭包函数,并将其返回值赋值为null,这样可以让闭包中的变量及时被垃圾回收器回收。
2.使用立即执行函数:在创建闭包时,将需要保留的变量传递给一个立即执行函数,并将这些变量作为参数传递给闭包函数,这样可以保留所需的变量,而不会导致其他变量的内存泄漏。





4. 垃圾回收机制

更详细内容: https://juejin.cn/post/
引用数据类型保存在堆内存中,基础类型保存在栈内存中
js定期找到那些不再使用的内存,将其释放掉。两种常见的垃圾回收算法:引用计数法和标记清除法。
标记清除法分为标记和清除两个阶段,标记阶段从根部(全局对象)出发定时扫描内存中的对象,凡是能从根部到达的对象,都是还需要使用的,做上标记,清除阶段则把没有标记的对象(非可达对象)销毁。
引用计数法主要记录对象有没有被其他对象引用,如果没有被引用,它将被垃圾回收机制回收。它的策略是跟踪记录每个变量值被使用的次数,当变量值引用次数为0时,垃圾回收机制就会把它清理掉。
为什么需要垃圾回收: 程序的运行需要内存,只要程序提出要求,操作系统或者运行时就必须提供内存,那么对于持续运行的服务进程,必须要及时释放内存,否则,内存占用越来越高,轻则影响系统性能,重则就会导致进程崩溃




5. 对象作用域,原型链

详细内容:https://blog.csdn.net/Yi_qian1000/article/details/

在这里插入图片描述
在这里插入图片描述

每个对象都有一个原型(prototype),它指向另外一个对象,而指向的对象又存在属性(proto)指向另外一个对象。当我们访问对象(obj3)的属性时,会先在对象定义的属性中进行查找,没找到就会沿着__proto__一路向上查找,最终形成一个链式结构,这整个链式结构就叫做原型链。

6. bind, call, apply

bind() 里面传递的是对应指向的对象
call() 里面传递的是指向的对象和参数(会自动调用)
apply() 里面传递是指向的对象及参数数组(会自动调用)
相同点:call、apply和bind都是JS函数的公有的内部方法,他们都是重置函数的this,改变函数的执行环节。
不同点:bind是创建一个新的函数,而call和aplay是用来调用函数;call和apply作用一样,只不过call为函数提供的参数是逗号分割,而apply为函数提供的参数是一个数组。



7. 进程与线程

CPU是计算机的核心,承担所有的计算任务。进程是CPU资源分配的最小单位,进程包括运行中的程序和程序所使用到的内存和系统资源。
线程是CPU调度的最小单位。线程是建立在进程的基础上的一次程序运行单位,通俗点解释线程就是程序中的一个执行流,一个进程可以有多个线程。
进程是操作系统分配资源的最小单位,线程是程序执行的最小单位
一个进程由一个或多个线程组成,线程可以理解为是一个进程中代码的不同执行路线
进程之间相互独立,但同一进程下的各个线程间共享程序的内存空间(包括代码段、数据集、堆等)及一些进程级的资源(如打开文件和信号)
调度和切换:线程上下文切换比进程上下文切换要快得多。
JS的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程,否则会带来很复杂的同步问题。比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?





8. 事件循环

更详细内容:https://juejin.cn/post/
js是单线程的运行机制,先执行同步代码,所有同步代码都在主线程上执行,形成一个执行栈(又称调用栈,先进后出)。
2. 当遇到异步任务时,会将其挂起并添加到任务队列中(先进先出),宏任务放入宏任务队列,微任务放进微任务队列。
3. 当执行栈为空时,事件循环先从微任务队列中按顺序取出任务,加入到执行栈中执行。如果微任务队列清空,就从宏任务队列中取出任务加入执行栈中执行。
4. 重复上述步骤,直到任务队列为空。



首先,整体的script(作为第一个宏任务)开始执行的时候,会把所有代码分为同步任务、异步任务两部分
同步任务会直接进入主线程依次执行
异步任务会再分为宏任务和微任务
宏任务进入到Event Table中,并在里面注册回调函数,每当指定的事件完成时,Event Table会将这个函数移到Event Queue中
微任务也会进入到另一个Event Table中,并在里面注册回调函数,每当指定的事件完成时,Event Table会将这个函数移到Event Queue中
当主线程内的任务执行完毕,主线程为空时,会检查微任务的Event Queue,如果有任务,就全部执行,如果没有就执行下一个宏任务
上述过程会不断重复,这就是Event Loop,比较完整的事件循环





定时器线程,异步http请求线程,事件触发线程

9. 浅拷贝,深拷贝

深拷贝和浅拷贝都是对象的拷贝,都会生成一个看起来相同的对象,他们本质的区别是拷贝出来的对象的地址是否和原对象一样,浅拷贝是地址的复制,深拷贝值的复制
在这里插入图片描述

10. 普通函数与箭头函数的区别

语法简洁性: 箭头函数的语法相对于普通函数更加简洁。箭头函数可以使用箭头来定义,省略了function关键字和花括号,可以直接定义函数的参数和返回值。
this 指向: 在普通函数中,this的值是在函数被调用时确定的,它指向调用该函数的对象。而在箭头函数中,this的值是在函数定义时确定的,它指向定义箭头函数的上下文。这意味着箭头函数没有自己的this,它继承父级作用域的this。
箭头函数不适用于构造函数: 箭头函数不能用作构造函数,不能通过new关键字来实例化对象。因为箭头函数没有原型对象。
arguments对象: 在普通函数中,可以使用arguments对象来访问所有传入的参数,它是一个类数组对象。而箭头函数没有自己的arguments对象,它继承父级作用域中的arguments对象。
函数声明提升: 普通函数有函数声明提升,可以在函数声明前调用函数;箭头函数有变量提升,没有函数声明提升,要在函数声明后调用函数



11. var let const 区别

作用域不同: let const具有块级作用域,var不存在块级作用域,可以跨块访问
变量提升: var存在变量提升,let和const不存在变量提升
全局属性: var声明的变量为全局变量,会将该变量添加为全局对象的属性,但是let和const不会。
重复声明: var声明变量时,可以重复声明变量,后声明的同名变量会覆盖之前声明的遍历。const和let不允许重复声明变量
初始值设置: 在变量声明时,var 和 let 可以不用设置初始值。而const声明变量必须设置初始值。
不可变: var 与 let声明的变量值可以更改,const不可更改。




12. 空间复杂度与时间复杂度

空间复杂度也就是 S(n) ,就是对一个算法或者说一段代码在运行过程中占用存储空间大小表达方式,用大O表示法来表示。存储空间是由声明的变量决定的,关于分析空间复杂度,其实我们直接从声明的变量入手就可以,看函数体内声明的变量根据传入值的变化而变化来分析。递归函数,每层递归里都会开辟一个递归栈,每次递归产生的变量等空间消耗都会存在递归栈中,这也是一个空间,不管你有没有声明变量,只要递归了递归栈它都存在,也就是说只要存在递归的情况,基本上最少的空间复杂度也是 O(n) 了,所以我们尽可能的在能使用迭代的情况下就不使用递归。

13. 重绘与回流

更详细内容:https://juejin.cn/post/
回流(Reflow)
当渲染树中的元素因为尺寸,位置,隐藏等改变而需要重新构建。这就称为回流(reflow)。在页面第一次加载的时候,会发生回流的,因为要构建render tree。在回流的时候,浏览器会使渲染树中受到影响的部分失效,并重新构造这部分渲染树,完成回流后,浏览器会重新绘制受影响的部分到屏幕中,该过程称为重绘。
简单来说,回流就是计算元素在设备内的确切位置和大小并且重新绘制
回流的代价要远大于重绘。并且回流必然会造成重绘,但重绘不一定会造成回流。
重绘(Repaint)
当渲染树中的一些元素需要更新样式,但这些样式属性只是改变元素的外观,而不会影响布局的,比如background-color。则就叫称为重绘(repaint)。
简单来说,重绘就是将渲染树节点转换为屏幕上的实际像素,不涉及重新布局阶段的位置与大小计算。
优化
样式集中改变(减少重排次数)合并对DOM样式的修改,采用css class来修改
将 DOM 离线(减少重排次数): display:none
脱离文档流(减小重排范围): absolute 或 fixed










14. es6 中处理异步的方式有哪些?

Promise,generator , async await

15. 检查数据类型的方法有哪些?

示例 https://blog.csdn.net/q/article/details/

  • typeof 这是最常用的基本数据类型检测的方法
  • instanceof 可以检测复杂数据类型,但是字面量方式创建的 String Number Boolean 无法匹配类型
  • constructor 改原型(prototype)就会改变类型
  • Object.prototype.toString.call()
16. 为什么 typeof null === ‘object’?

因为不同的对象在底层都表示为二进制, 在 JavaScript 中二进制前三位都为 0 的话会被判断为 object 类型, null 的二进制表示是全 0, 自然前三位也是 0, 所以执行 typeof 时会返回“object”。实际上是JS设计时的bug。

17. typeof 与 instance 区别
 
  

typeof 用于返回一个变量或表达式的数据类型的字符串表示。它对于原始数据类型(如字符串、数字和布尔值)特别有用,但对于识别具体的对象类型(如区分数组和对象)则不那么有效。

instanceof 用于检查一个对象是否为一个特定构造函数的实例,或者说对象的原型链上是否存在构造函数的 prototype 属性(更准确地说,它检查右侧构造函数的 prototype 属性是否存在于左侧对象的原型链上。)


typescript

1. ts 有什么优势?
  • ts 提供了静态类型检查,在编译阶段就能发现很多类型相关的错误,而不是等到运行时。这可以显著提高代码的质量,减少调试时间。
  • 通过明确的类型定义和接口,可以快速了解函数、变量和类的用途和预期行为,使代码更加易于理解和维护。
2. type interface区别

更详细内容: https://blog.csdn.net/_/article/details/
相同点:
都可以描述对象和函数;
都允许拓展,interface(extends)type(&);
都可以使用 typeof 获取实例的类型。
都可以实现继承
不同点:
type可以声明基本类型别名,交叉类型(&),联合类型(|),元组等;
interface能够重复声明,并自动合并,type重复声明会报错;








vue

1. 如何实现数据的双向绑定?

vue2 通过 object.defineProperty 来劫持对象的各个属性的setter,getter,在数据发生变化时,通知给订阅者,触发响应的监听回掉。
具体流程:
第一步:数据监听器Observer,能够对数据对象的所有属性进行监听,如有变动可拿到最新的值并通知订阅者
第二步:指令解析器Compile,对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数
第三步:Watcher作为连接Observer和Compile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图
第四步:MVVM作为数据绑定的入口,整合Observer、Compile和watcher三者,通过Observer监听自己的model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭建起Observer和Compile之间的通信桥梁达到数据双向绑定效果




2. 虚拟dom 的优势?

提升性能:虚拟DOM可以将多次DOM操作合并为一次,通过diff算法找出需要更新的部分,只对这些部分进行操作,而不是整个DOM树。相比直接操作真实DOM,这样可以大幅度减少DOM操作的次数,提高性能。

跨平台兼容性:虚拟DOM是基于JavaScript对象树,因此可以在不同平台上使用相同的代码逻辑。一套代码多端运行。

开发效率提升:虚拟DOM可以将视图和状态分离,通过声明式的方式描述用户界面,提供了更高级别的抽象。更专注于业务逻辑,减少了手动操作DOM的复杂性,提高开发效率。

缺点: 是因为首次渲染大量 dom,由于多一层虚拟 dom 计算,速度比正常稍慢。

3. 路由钩子

更详细内容:https://blog.csdn.net/a/article/details/
组件内的路由守卫:beforeRouteEnter beforeRouterUpdate beforeRouteLeave
全局路由守卫:beforeEach afterEach
单个路由守卫:beforeEnter


4. vue 为什么不是fiber

更详细内容: https://blog.csdn.net/frontend_frank/article/details/
react、vue的响应式原理不同: 在react中,组件的状态是不能被修改的,setState没有修改原来那块内存中的变量,而是去新开辟一块内存,setState后,会自顶向下重新渲染组件,该组件以及它的子组件全部需要渲染;而vue则是直接修改保存状态的那块原始内存,使用Object.defineProperty(vue@3迁移到了Proxy)对数据的设置(setter)和获取(getter)做了劫持,也就是说,vue能准确知道视图模版中哪一块用到了这个数据,并且在这个数据修改时,告诉这个视图,你需要重新渲染了。
所以当一个数据改变,react的组件渲染是很消耗性能的——父组件的状态更新了,所有的子组件得跟着一起渲染,它不能像vue一样,精确到当前组件的粒度。
react 有更大的diff压力: 在数据更新时,react生成了一棵更大的虚拟dom树,给diff带来了很大压力——我们想找到真正变化的部分,这需要花费更长的时间。js占据主线程去做比较,渲染线程便无法做其他工作,用户的交互得不到响应,所以便出现了react fiber。
react fiber没法让比较的时间缩短,但它使得diff的过程被分成一小段一小段的,因为它有了“保存工作进度”的能力。js会比较一部分虚拟dom,然后让渡主线程,给浏览器去做其他工作,然后继续比较,依次往复,等到最后比较完成,一次性更新到视图上。



5. vue2 和 vue3 区别?

双向绑定方法不同: Vue2 采用object.defineProperty来实现双向绑定。只能监听对象的单个属性,不能对整个对象进行监听。object.defineProperty后添加的属性劫持不到,可能导致数据更新但视图不更新的问题。
Vue3 使用new Proxy来完成双向绑定。Proxy可以监听整个对象及其属性的变化,包括新增和删除属性,同时还能更好地处理数组的变化。

生命周期: Vue 3‌中的生命周期钩子函数也有所变化,beforeCreate 和 created 被setup函数替代,其他钩子函数如beforeMount、mounted等则需要在Vue 3中显式引入并使用,取消 beforeDestroyed、destroyed,新增 onBeforeUnmount、onUnmounted。

碎片化: Vue 3‌支持碎片(Fragments),即组件可以有多个根节点,而Vue 2则只能有一个根节点。

API设计: Vue 2‌:使用选项式API(Options API),将组件的不同部分(如数据、计算属性、方法等)分割到不同的选项中。
‌Vue 3‌:引入了组合式API(Composition API),允许开发者使用函数来组织逻辑,这种方式使得代码更加灵活和可重用。组合式API还提供了更好的TypeScript支持,提高了代码的可维护性和可读性。

性能优化: Vue 3‌在性能上进行了多项优化,包括采用了新的编译器,显著提高了编译速度和性能;支持完整的树摇(tree-shaking),只包含需要的代码,减小了捆绑大小;响应式性仅限于定义它们的组件,提高了性能。

新功能: Vue 3‌引入了多个新功能,如Suspense API,允许开发者更好地处理异步组件和数据加载;全面支持TypeScript类型注解;移除了v-on.native修饰符,改为在emits选项中定义组件触发的事件;移除了过滤器(filter),推荐使用计算属性(computed)和方法(method)来替代。

其他差异: ‌Vue 3‌中的v-model指令得到了优化,可以直接绑定多个属性,而在Vue 2中则需要使用.sync修饰符来实现类似功能。

6. vue中为什么没有 react 中的 shouldComponentUpdate?

react中,调用setState方法后,会自顶向下重新渲染组件,该组件以及它的子组件全部需要渲染,所以可以使用shouldComponentUpdate来判断组件是否确实需要更新;而vue使用Object.defineProperty(vue@3迁移到了Proxy)对数据的设置(setter)和获取(getter)做了劫持,也就是说,vue能准确知道视图模版中哪一块用到了这个数据,并且在这个数据修改时,只更新必要的部分,而不是整个组件。

7. react 和 vue 区别

相同:
数据驱动视图
组件化
Virtual DOM


不同:

响应式原理不同:Vue 通过数据劫持,能精确知道数据变化。react 通过比较引用方式(diff)进行的,当应用的状态改变时,全部组件都会重新渲染。

数据流的不同:Vue 可以数据双向绑定,React一直不支持双向绑定,提倡的是单向数据流(onChange/setState)。

组件语法不通:React 推荐使用 JSX 语法,也就是把 HTML 和 CSS 全都写进 JavaScript 中;Vue 推荐的做法是 template 的单文件组件格式,即 HTML,CSS,JS 写在同一个文件(Vue 也支持 JSX 写法)。

渲染过程不同:Vue可以更快地计算出Virtual DOM的差异,这是由于它在渲染过程中,会跟踪每一个组件的依赖关系,不需要重新渲染整个组件树。React在应用的状态被改变时,全部子组件都会重新渲染。通过shouldComponentUpdate这个生命周期方法可以进行控制。


react

1. react key的作用
2. 为什么多个 JSX 标签需要被一个父元素包裹?

JSX 虽然看起来很像 HTML,但在底层其实被转化为了 JavaScript 对象,你不能在一个函数中返回多个对象,除非用一个数组把他们包装起来。这就是为什么多个 JSX 标签必须要用一个父元素或者 Fragment 来包裹。

3. react diff算法, fiber

更详细内容: https://juejin.cn/post/
diff: react 是基于 vdom 的前端框架,组件渲染产生 vdom,渲染器把 vdom 渲染成 dom。
浏览器下使用 react-dom 的渲染器,会先把 vdom 转成 fiber,找到需要更新 dom 的部分,打上增删改的 effectTag 标记,这个过程叫做 reconcile,可以打断,由 scheducler 调度执行。reconcile 结束之后一次性根据 effectTag 更新 dom,叫做 commit。
这就是 react 的基于 fiber 的渲染流程,分成 render(reconcile + schedule)、commit 两个阶段。
当渲染完一次,产生了 fiber 之后,再次渲染的 vdom 要和之前的 fiber 对比下,再决定如何产生新的 fiber,目标是尽可能复用已有的 fiber 节点,这叫做 diff 算法。
react 的 diff 算法分为两个阶段:
第一个阶段一一对比,如果可以复用就下一个,不可以复用就结束。
第二个阶段把剩下的老 fiber 放到 map 里,遍历剩余的 vdom,一一查找 map 中是否有可复用的节点。
最后把剩下的老 fiber 删掉,剩下的新 vdom 新增。
这样就完成了更新时的 reconcile 过程。
其实 diff 算法的核心就是复用节点,通过一一对比,map 查找找到可复用的节点,移动过,然后剩下的该删删该增增。
fiber: react fiber没法让比较的时间缩短,但它使得diff的过程被分成一小段一小段的,因为它有了“保存工作进度”的能力。js会比较一部分虚拟dom,然后让渡主线程,给浏览器去做其他工作,然后继续比较,依次往复,等到最后比较完成,一次性更新到视图上。










每个节点有三个指针:分别指向第一个子节点、下一个兄弟节点、父节点。这种数据结构就是fiber,深度优先,它的遍历规则如下:

  1. 从根节点开始,依次遍历该节点的子节点、兄弟节点,如果两者都遍历了,则回到它的父节点;
  2. 当一个节点的所有子节点遍历完成,才认为该节点遍历完成;

当遍历发生中断时,只要保留下当前节点的索引,断点是可以恢复的——因为每个节点都保持着对其父节点兄弟节点的索引。

4. fiber继续对比的时机?

更详细内容https://blog.csdn.net/_/article/details/

5. setState是同步还是异步?
6. 为什么hooks只能在顶层调用?(hooks怎么存储)

更详细内容https://blog.csdn.net/dwf_H/article/details/
函数组件渲染分两种场景: 首次渲染、更新组件。函数组件在首次渲染的时候,碰到hook语句时,是去创建一个空的hook对象挂载在memorizeState上,然后依次挂在next上。
而更新时,他不会重新依次创建空的hook对象,而是去上一次的memorizeState上按照顺序,依次去取hook对象并且赋值。
所以必须保证每次渲染执行函数组件时,hook语句不会因为什么别的条件而导致顺序或者数量变了。


webpack

更多详细内容:https://juejin.cn/post/?searchId=A0B5F5C12208A6FA0#heading-11
https://juejin.cn/post/?searchId=A0B5F5C12208A6FA0
https://juejin.cn/post/?searchId=B4FF2FABB1A9DC7

1. webpack 构建流程

Webpack 的运行流程是一个串行的过程,从启动到结束会依次执行以下流程:
初始化参数: 从配置文件和 Shell 语句中读取与合并参数,得出最终的参数
开始编译: 用上一步得到的参数初始化 Compiler 对象,加载所有配置的插件,执行对象的 run 方法开始执行编译
确定入口: 根据配置中的 entry 找出所有的入口文件
编译模块: 从入口文件出发,调用所有配置的 Loader 对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理
完成模块编译: 在经过第4步使用 Loader 翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系
输出资源: 根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会
输出完成: 在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统
整个过程中webpack会通过发布订阅模式,向外抛出一些hooks,而webpack的插件即可通过监听这些关键的事件节点,执行插件任务进而达到干预输出结果的目的。







2. webpack的主要作用如下:

模块打包。可以将不同模块的文件打包整合在一起,并且保证它们之间的引用正确,执行有序。
编译兼容。通过webpack的Loader机制,不仅仅可以帮助我们对代码做polyfill,还可以编译转换诸如.less,.vue,.jsx这类在浏览器无法识别的格式文件,让我们在开发的时候可以使用新特性和新语法做开发,提高开发效率。
能力扩展。通过webpack的Plugin机制,我们在实现模块化打包和编译兼容的基础上,可以进一步实现诸如按需加载,代码压缩等一系列功能,帮助我们进一步提高自动化程度,工程效率以及打包输出的质量。

3. 不同环境需求

本地环境:
需要更快的构建速度
需要打印 debug 信息
需要 live reload 或 hot reload 功能
需要 sourcemap 方便定位问题

生产环境:
需要更小的包体积,代码压缩+tree-shaking
需要进行代码分割
需要压缩图片体积








4. loader

loader 是负责对其他类型的资源进行转译的预处理工作

 
     
5. plugins

Plugin 插件可以扩展 Webpack 的功能,在 Webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果。

 
     
6. Webpack 的热更新原理

深度解析:https://zhuanlan.zhihu.com/p/
Hot Module Replacement,HMR的核心就是客户端从服务端拉去更新后的文件,准确的说是 chunk diff (chunk 需要更新的部分),实际上 WDS 与浏览器之间维护了一个 Websocket,当本地资源发生变化时,WDS 会向浏览器推送更新,并带上构建时的 hash,让客户端与上一次资源进行对比。客户端对比出差异后会向 WDS 发起 Ajax 请求来获取更改内容(文件列表、hash),这样客户端就可以再借助这些信息继续向 WDS 发起 jsonp 请求获取该chunk的增量更新。
后续的部分(拿到增量更新之后如何处理?哪些状态该保留?哪些又需要更新?)由 HotModulePlugin 来完成,提供了相关 API 以供开发者针对自身场景进行处理,像react-hot-loader 和 vue-loader 都是借助这些 API 实现 HMR。

7. 优化

代码懒加载 预加载

8. Webpack 有什么 Api?

更多详细内容: https://blog.csdn.net/handsomezhanghui/article/details/

9. splitchunk

css

1. rem em

rem 是基于html元素字体大小来决定的,em 是根据使用它的元素字体大小来计算的。

2. flex

更多详细内容: http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html

  1. 采用flex布局的元素称为父容器,它的子元素称为项目,通过设置主轴,交叉轴可以控制项目的排列方式。
  2. 父容器属性:6个
    flex-direction : 决定主轴的方向 row row-reverse column column-reverse
    flex-wrap : 定义如果一条轴线排不下,如何换行 nowrap wrap wrap-reverse
    flex-flow: 是flex-direction属性和flex-wrap属性的简写
    justify-content:定义了项目在主轴上的对齐方式 flex-start flex-end center space-around space-between
    align-items: 定义项目在交叉轴上对齐方式 flex-start flex-end center stretch baseline
    align-content: 定义了多根轴线的对齐方式 flex-start flex-end cend stretch space-around space-between





  3. 项目属性 6个
    order: 定义项目的排列顺序。数值越小,越靠前,默认0
    flex-grow: 定义项目的放大比例。默认0,即存在剩余空间,不放大
    flex-shrink: 定义项目的缩小比例。默认1,即空间不足,项目将缩小
    flex-basis:定义了在分配多余空间之前,项目占据的主轴空间。它的默认值为auto,即项目的本来大小。
    flex:是flex-grow, flex-shrink 和 flex-basis的简写,默认值为0 1 auto
    align-self:允许单个项目有与其他项目不一样的对齐方式。可覆盖align-items属性 auto flex-start flex-end center stretch baseline





网络

1. https 是什么?

https 是超文本传输安全协议, 在 HTTP(超文本传输协议)的基础上加入了 SSL/TLS(安全套接层/传输层安全)协议,以提供加密通信和身份验证的功能。主要目的是确保数据传输的安全性和完整性。通过使用加密技术,HTTPS 可以防止数据在传输过程中被窃听或篡改。同时,HTTPS 还通过数字证书进行身份验证,确保用户正在与正确的服务器通信,而不是被伪装的恶意服务器。

2. https如何建立连接

https 建立连接的过程包括TCP三次握手和SSL/TLS握手。TCP三次握手用于建立可靠的连接,而SSL/TLS握手则用于确保通信双方的身份验证和加密通信。通过这个过程,HTTPS能够提供安全、可靠的数据传输服务。

2.1 tcp 三次握手

在这里插入图片描述
tcp 三次握手 需要客户端和服务器总共发送3个报文。这个过程确保了双方都能够准备好发送和接收数据,同时也为双方后续的数据传输设置了初始的序列号,以便正确地对数据进行排序和确认。
第一次握手:
客户端将TCP报文标志位SYN置为1,随机产生一个序号值seq=J,保存在TCP首部的序列号(Sequence Number)字段里,指明客户端打算连接的服务器的端口,并将该数据包发送给服务器端,发送完毕后,客户端进入SYN_SENT状态,等待服务器端确认。
第二次握手:
服务器端收到数据包后由标志位SYN=1知道客户端请求建立连接,服务器端将TCP报文标志位SYN和ACK都置为1,ack=J+1,随机产生一个序号值seq=K,并将该数据包发送给客户端以确认连接请求,服务器端进入SYN_RCVD状态。
第三次握手:
客户端收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给服务器端,服务器端检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,客户端和服务器端进入ESTABLISHED状态,完成三次握手,随后客户端与服务器端之间可以开始传输数据了。






2.2 SSL/TLS握手
  1. 客户端向服务端发送消息,包含客户端支持的ssl/tls协议列表,加密套件列表,随机数等
  2. 服务端回复消息,包含选定的ssl/tls协议,加密套件,随机数等,并包含服务器证书,公钥
  3. 客户端验证服务器证书的有效性,无效则断开连接
    4.通过后,客户端生成一个预主密钥,并通过证书中的公钥进行加密,发送给服务器,同时根据随机数生成会话密钥
  4. 服务器使用自己的私钥解密该预主密钥,同样生成会话密钥,与客户端一致
  5. 至此TLS连接建立完成,可以开始传输数据,并且使用同一个私钥密钥来加解密。
3. 输入网址到页面渲染发生了什么
  1. DNS解析:浏览器首先会检查缓存中是否有该网址的IP地址,如果没有,则会向DNS(域名系统)服务器查询该网址对应的IP地址。DNS服务器会将域名解析成对应的IP地址,这样浏览器才能通过IP地址找到服务器。
  2. 建立连接:浏览器使用IP地址找到对应的服务器,并通过HTTP(超文本传输协议)或HTTPS(安全的HTTP)协议与服务器建立连接。在HTTPS连接中,还会涉及到SSL/TLS加密的过程。
  3. 发送请求:连接建立后,浏览器会向服务器发送一个HTTP请求报文,请求中包含了请求的方法(如GET或POST)、请求的资源的路径等信息。
  4. 服务器响应:服务器接收到请求后,会处理请求并生成HTTP响应报文。如果请求的是静态资源(如HTML、CSS、图片等),服务器会直接返回这些文件;如果请求的是动态资源,服务器会根据应用程序逻辑生成相应的HTML页面等数据。
  5. 浏览器渲染:浏览器接收到服务器响应的数据后,会开始进行渲染。这个过程包括解析HTML文档,构建DOM(文档对象模型)树,解析CSS并将其应用到DOM树上,执行JavaScript代码,以及布局和绘制最终的页面。
  6. 加载资源:在渲染页面的过程中,如果发现需要额外的资源(如图片、CSS文件、JavaScript文件等),浏览器会继续通过HTTP请求获取这些资源,并将它们应用到页面上。
  7. 交互处理:当页面加载完成后,用户就可以与页面进行交互。用户的操作可能会触发更多的HTTP请求,比如点击链接或提交表单。
4. post请求与get请求的区别?

更多详细内容https://blog.csdn.net/weixin_/article/details/

  • 浏览器回退表现不同:GET会将请求参数附加到URL的查询字符串中,不会产生副作用,因此在浏览器回退时会自动从缓存中获取该页面并显示出来,而POST将请求参数包含在HTTP请求体中,可能导致对服务器状态进行更改,因此回退时会再次提交请求。
  • 编码方式不同:GET请求只能进行url编码,而POST支持多种编码方式。
  • 参数大小不同:GET请求在URL中传送的参数是有长度限制的,而POST没有。
  • 安全性不同:GET参数通过URL传递,POST放在Request body中, GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
到此这篇node 面试(node面试题整理简书)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!

版权声明


相关文章:

  • json转map保留null(jsonnode转map)2025-06-26 09:54:08
  • 升级node版本会影响项目吗安全吗(升级node版本会影响项目吗安全吗知乎)2025-06-26 09:54:08
  • 安装node.js报错invalid drive(win7安装node.js 报错)2025-06-26 09:54:08
  • 安装node的命令(命令行安装node)2025-06-26 09:54:08
  • node版本控制(node控制台)2025-06-26 09:54:08
  • nvm安装node失败(安装node报错)2025-06-26 09:54:08
  • nvm切换node版本(nvm切换node版本命令 切换了 实际无效)2025-06-26 09:54:08
  • nodejs安装nrm报错(node安装完node –v报错)2025-06-26 09:54:08
  • npm 升级nodejs(npm 升级包内依赖)2025-06-26 09:54:08
  • node包管理工具(node包管理工具有哪些)2025-06-26 09:54:08
  • 全屏图片