个人总结前端面试题(持续更新中)

package.json中版本号的规则

package.json中版本号的规则:
主版本号.次版本号.修补版本号
patch:修复bug,兼容老版本
minor:新增功能,兼容老版本
major:新的架构调整,不兼容老版本
依赖版本号规则
version
必须匹配某个版本
如:1.1.2,表示必须依赖1.1.2版
version
必须大于某个版本
如:>1.1.2,表示必须大于1.1.2版
=version
可大于或等于某个版本
如:>=1.1.2,表示可以等于1.1.2,也可以大于1.1.2版本
<version
必须小于某个版本
如:<1.1.2,表示必须小于1.1.2版本
<=version
可以小于或等于某个版本
如:<=1.1.2,表示可以等于1.1.2,也可以小于1.1.2版本
~version
大概匹配某个版本
如果minor版本号指定了,那么minor版本号不变,而patch版本号任意
如果minor和patch版本号未指定,那么minor和patch版本号任意
如:~1.1.2,表示>=1.1.2 <1.2.0,可以是1.1.2,1.1.3,1.1.4,…,1.1.n
如:~1.1,表示>=1.1.0 <1.2.0,可以是同上
如:~1,表示>=1.0.0 <2.0.0,可以是1.0.0,1.0.1,1.0.2,…,1.0.n,1.1.n,1.2.n,…,1.n.n
^version
兼容某个版本
版本号中最左边的非0数字的右侧可以任意
如果缺少某个版本号,则这个版本号的位置可以任意
如:^1.1.2 ,表示>=1.1.2 <2.0.0,可以是1.1.2,1.1.3,…,1.1.n,1.2.n,…,1.n.n
如:^0.2.3 ,表示>=0.2.3 <0.3.0,可以是0.2.3,0.2.4,…,0.2.n
如:^0.0,表示 >=0.0.0 <0.1.0,可以是0.0.0,0.0.1,…,0.0.n
x-range
x的位置表示任意版本
如:1.2.x,表示可以1.2.0,1.2.1,…,1.2.n
-range
任意版本,""也表示任意版本
如:
,表示>=0.0.0的任意版本
version1 - version2
大于等于version1,小于等于version2
如:1.1.2 - 1.3.1,表示包括1.1.2和1.3.1以及他们件的任意版本
range1 || range2
满足range1或者满足range2,可以多个范围
如:<1.0.0 || >=2.3.1 <2.4.5 || >=2.5.2 ❤️.0.0,表示满足这3个范围的版本都可以

AMD、CMD、commonJS模块化规范的区别

CommonJS是同步加载模块,是以在浏览器环境之外构建 JavaScript 生态系统为目标而产生的项目,比如在服务器和桌面环境中,Node.JS遵循CommonJS的规范
CommonJS 规范是为了解决 JavaScript 的作用域问题而定义的模块形式,可以在每个模块它自身的命名空间中执行。该规范的主要内容是,模块必须通过 module.exports 导出对外的变量或接口,通过 require() 来导入其他模块的输出到当前模块作用域中。

AMD是异步模块定义,它主要异步方式加载模块,模块的加载不影响它后面语句的运行。AMD也采用require()语句加载模块,但是不同于CommonJS,它要求两个参数:第一个参数是一个数组,表示所依赖的模块,第二个参数是回调函数,在当前指定的模块都加载成功后会被调用

CMD, 是seajs推崇的规范,CMD则是依赖就近,用的时候再require(什么时候用什么时候引,不需要提前定义在代码的顶部)。AMD和CMD最大的区别是对依赖模块的执行时机处理不同,而不是加载的时机或者方式不同,二者皆为异步加载模块。AMD依赖前置,js可以方便知道依赖模块是谁,立即加载;而CMD就近依赖,需要使用把模块变为字符串解析一遍才知道依赖了那些模块
[^1]: mermaid语法说明

package.json中版本号的规则

Jsx是javascript的一种语法扩展,它和模板语言很相似
过程:jsx需要通过babel进行转换为react.createElement,
React.createElement需要传入三个参数:
第一个参数为type:有四种类型(原生标签节点:type的类型为字符串,文本节点:type就是TEXT,函数组件:type就是函数的名称,class类组件:type:就是这个类的名称)
第二个参数:config,会将组件中的所有属性提取出来并保存起来
第三个参数:children,用来保存组件之间嵌套的内容,子节点或子元素
React.createElement:首先会将config中的ref,self,corsous等属性进行二次处理,
然后再将children中的子元素提取到childArray这个数组中,将这些数据进行一个reactElement的回调,进而构成虚拟dom
最后,这个虚拟dom会通过ReactDom.render,转化为展示dom

什么是强缓存和协商缓存

浏览器在第一次请求发生后,再次发起请求时:浏览器请求某一资源时,会先获取该资源缓存的header信息,然后根据header中的Cache-Control和Expires来判断是否过期,若没过期则直接从缓存中获取资源信息,包括缓存的header的信息,所以此次请求不会与服务器进行通信,这一过程就是强缓存,又叫做本地缓存
如果显示已过期,浏览器会向服务器端发送请求,这个请求会携带第一次请求返回的有关缓存的header字段信息,比如客户端会通过if-None-Match头将先前服务器端发送过来的Etag发送给服务器,服务器会对比这个客户端发过来的etag是否与服务器的相同,如果相同,就将if-None-Match的值设为false,返回状态304,客户端继续使用本地缓存,不解析服务器端发回来的数据,若不相同就将If-None-Match的值设为true,返回状态为200,客户端重新解析服务器端返回的数据;客户端还会通过If-Modified-Since头将先前服务器端发过来的最后修改时间戳发送给服务器,服务器端通过这个时间戳判断客户端的页面是否是最新的,如果不是最新的,则返回最新的内容,如果是最新的,则返回304,客户端就会继续使用本地缓存,这一过程就属于协商缓存又叫做弱缓存

前端性能优化的手段

避免使用内联函数
使用 React Fragments 避免额外标记
使用 Immutable
懒加载组件
事件绑定方式
服务端渲染

大文件如何做断点续传

首先将文件切片成多个块,每个块都有一个编号,依次上传,在全部上传完毕之后,通知后端,后端进行合并,如果传到某个块之后因为某些原因网断了,在下次每个切片上传之前,会先问一下后端,这一块的切片在不在(verify校验),后端会告诉你,这一块的切片在不在,如果在的话就会显示切片上传成功了,如果不在的话,会接着之前的继续往后下载

说说React服务端渲染怎么做?原理是什么

在react中,实现SSR主要有两种形式:
手动搭建一个 SSR 框架
使用成熟的SSR 框架,如 Next.JS
但是像一些事件处理的方法,是无法在服务端完成,因此需要将组件代码在浏览器中再执行一遍,这种服务器端和客户端共用一套代码的方式就称之为同构
重构通俗讲就是一套React代码在服务器上运行一遍,到达浏览器又运行一遍:
服务端渲染完成页面结构
浏览器端渲染完成事件绑定
浏览器实现事件绑定的方式为让浏览器去拉取JS文件执行,让JS代码来控制,因此需要引入script标签
整体react服务端渲染原理并不复杂,具体如下:
node server 接收客户端请求,得到当前的请求url 路径,然后在已有的路由表内查找到对应的组件,拿到需要请求的数据,将数据作为 props、context或者store 形式传入组件
然后基于 react 内置的服务端渲染方法 renderToString()把组件渲染为 html字符串在把最终的 html进行输出前需要将数据注入到浏览器端
浏览器开始进行渲染和节点对比,然后执行完成组件内事件绑定和一些交互,浏览器重用了服务端输出的 html 节点,整个流程结束。

自定义hook的理解

通过自定义hook,可以将组件逻辑提取到可重用的函数中,可以理解成hook就是用来方一些重复代码的函数的。所谓的自定义hook,实际上就是把很多重复的逻辑都放在一个函数里面,通过闭包的方式return出去,这是非常高级的方式,如果在以后业务开发时需要大量的重复代码,我们就可以将它封装成自定义hook

说说react diff的原理是什么

跟Vue一致,React通过引入Virtual DOM的概念,极大地避免无效的Dom操作,使我们的页面的构建效率提到了极大的提升
而diff算法就是更高效地通过对比新旧Virtual DOM来找出真正的Dom变化之处
react中diff算法主要遵循三个层级的策略:tree层,component层,element层
在tree层,dom节点跨层级的操作不做优化,只会对相同层级的节点进行比较,只进行删除和创建操作,没有移动操作
在component层,如果是同一个类的组件,则会继续往下diff运算,如果不是一个类的组件,那么直接删除这个组件下的所有子节点,并且创建新的节点
在element层,对于比较同一层级的节点们,每个节点在对应的层级用唯一的key作为标识,提供了3中操作,分别是插入,移动和删除

react渲染过程

渲染方式分为三种:(1)component–每次都会触发组件的生命周期(2)render–内联模式渲染,性能会更高,props需要传递到函数内(3)children–会一直渲染不管匹配模式
过程:react渲染整个渲染机制就是react渲染会调用函数render()构建一个新的虚拟dom树,在state或props发生改变的时候,reader()函数会被调用,构造出另外一棵树的虚拟dom树,渲染所有节点,用新构造的新的虚拟dom树和原来的dom树进行比较,找到旧树和新树之间的差异,然后再渲染到真实的dom树上,这样就减少了对dom树的频繁操作,从而提升性能

keep-alive的实现原理

keep-alive是Vue的内置组件,当它包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。keep-alive是一个抽象组件,它自身不会渲染一个DOM元素,也不会出现在父组件中,主要作用是在组件切换过程中 把切换出去的组件保留在内存中,防止重复渲染DOM,减少加载时间及性能消耗,提高用户体验性。在 created钩子函数调用时将需要缓存的 VNode 节点保存在 this.cache 中/在 render(页面渲染) 时,如果 VNode 的 name 符合缓存条件(可以用 include 以及 exclude 控制),则会从 this.cache 中取出之前缓存的 VNode实例进行渲染。

ES6 模块与 CommonJS 模块存在以下差异

语法上:
CommonJS 使用的是 module.exports = {} 导出一个模块对象,require(‘file_path’) 引入模块对象;
ES6使用的是 export 导出指定数据, import 引入具体数据。
CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用:
CommonJS 模块输出的是值的拷贝,也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。
ES6 Modules 的运行机制与 CommonJS 不一样。JS 引擎对脚本静态分析的时候,遇到模块加载命令import,就会生成一个只读引用。等到脚本真正执行时,再根据这个只读引用,到被加载的那个模块里面去取值。原始值变了,import加载的值也会跟着变。因此,ES6模块是动态引用,并且不会缓存值,模块里面的变量绑定其所在的模块。
CommonJS 模块是运行时加载,ES6 模块是编译时加载:
运行时加载: CommonJS 模块就是对象;即在输入时是先加载整个模块,生成一个对象,然后再从这个对象上面读取方法,这种加载称为“运行时加载”。
编译时加载: ES6 模块不是对象,而是通过 export 命令显式指定输出的代码,import时采用静态命令的形式。即在import时可以指定加载某个输出值,而不是加载整个模块,这种加载称为“编译时加载”
PS:CommonJS 加载的是一个对象(即module.exports属性),该对象只有在脚本运行完才会生成。而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。

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

基本数据类型:number,string,boolean,undefined,null,symbol
复杂数据类型(引用类型):object(对象:以键值对的形式),array(数组:[]包裹,可以放任意数据类型(包括object)),function(函数:有三种表达方式:函数式声明,函数表达式,箭头函数),还包括:date,regexp,map,set等
区别:
基本数据类型的值存放在栈中,在栈中存放对应的值,而复杂数据类型的值是存储在堆中的,在栈中存放的是指向堆内存的地址
而且不同的数据类型在赋值变量时也是不同的:
基本数据类型在赋值时是生成相同的值,两个对象对应不同的地址
复杂数据类型在赋值时,是将保存对象的内存地址赋值给另一个变量,也就是两个变量指向堆内存中的同一个对象

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

回流:布局引擎会根据各种样式计算每个盒子在页面上的大小与位置
重绘:当计算好盒模型的位置、大小及其他属性后,浏览器根据每个盒子特性进行绘制
回流触发场景:
添加或删除可见的DOM元素
元素的位置发生变化
元素的尺寸发生变化(包括外边距、内边框、边框大小、高度和宽度等)
内容发生变化,比如文本变化或图片被另一个不同尺寸的图片所替代
页面一开始渲染的时候(这避免不了)
浏览器的窗口尺寸变化(因为回流是根据视口的大小来计算元素的位置和大小的)
重绘触发场景:
颜色的修改
文本方向的修改
阴影的修改

react 中jsx语法糖的本质

jsx本质React.createElement的语法糖,所有的jsx语法都会最终经过babel.js转化成为React.createElement这个函数的函数调用

说说你对koa中洋葱模型的理解

Koa是一个精简的node框架,被认为是第二代Node框架,其最大的特点就是独特的中间件流程控制,是一个典型的洋葱模型,它的核心工作包括下面两个方面:将node原生的req和res封装成为一个context对象。基于async/await的中间件洋葱模型机制。
Koa的洋葱模型是以next()函数为分割点,先由外到内执行Request的逻辑,然后再由内到外执行Response的逻辑,这里的request的逻辑,我们可以理解为是next之前的内容,response的逻辑是next函数之后的内容,也可以说每一个中间件都有两次处理时机。洋葱模型的核心原理主要是借助compose方法
为什么需要洋葱模型?
因为很多时候,在一个app里面有很多中间件,有些中间件需要依赖其他中间件的结果,用葱模型可以保证执行顺序,如果没有洋葱模型,执行顺序可能出乎我们的预期

说说你对webSocket的理解

什么是WebSocket

WebSocket是HTML5提供的一种浏览器与服务器进行全双工通讯的网络技术,属于应用层协议。

为什么需要WebSocket

传统上的HTTP协议它是无状态的,服务器不能够识别是哪个客户端发送的请求,不能够保存状态。
WebSocket弥补了这一问题,在客户端向服务端发送请求之后,服务器处理请求并返回到客户端,使用WebSocket可以使得服务器主动向浏览器推送消息
WebSocket与HTTP的区别:1、HTTP是客户端直接向服务端发送请求,WebSocket是在完成一次握手之后建立连接。2、发送HTTP请求的时候,服务器不能记住是谁发给他的。3、发送WebSocket请求,服务器可以记住是谁发给他的

原理:

与服务器进行三次握手,建立TCP连接。向服务器发送HTTP请求,请求中包含WebSocket的版本信息:包括upgrade、connection等等。

优点:建立WebSocket连接之后,客户端与服务端交流更方便。客户端只需要向服务端发送一次请求,服务端主动向客户端发送消息

缺点:在服务端的状态不会频繁变化的时候,就不需要使用WebSocket连接了,浪费性能

应用场景

基于websocket的事实通信的特点,其存在的应用场景大概有:
弹幕
媒体聊天
协同编辑
基于位置的应用
体育实况更新
股票基金报价实时更新

如何借助webpack来优化前端性能

JS代码压缩
CSS代码压缩
Html文件代码压缩
文件大小压缩
图片压缩
Tree Shaking
代码分离
内联 chunk

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值