20道面试题
1、HTML语义化标签
<header>
定义头部、包含标题、导航、作者信息等
<nav>
导航链接
<main>
文档主要内容
<artivle>
独立的内容块,例如一篇文章
<section>
文档中的区域或节,用于将内容分组
<aside>
通常用于侧边栏或者补充信息
<footer>
定义文档或底部,包含版权信息、联系信息
<figure>
包含图像或图表,附带说明
<time>
表示日期和时间
<mark>
突出显示文本
<address>
联系信息
语义化标签的好处:提高可读性、增强SEO、提高无障碍性
2、事件冒泡和捕获
捕获:是指事件从文档的根节点
向目标元素
传递的过程。在这个阶段,事件会从外层节点
逐层传递到目标元素
。可以通过addEventListener第三个参数指定为true来启用捕获
冒泡:是指事件从目标元素
向文档的根节点
传递的过程,在这个阶段,事件会从目标元素
逐层传递到外层节点
。 大多数事件以冒泡的方式进行
3、获取HTML元素的方法
document.getElementById // 获取ID元素
document.getElementsByClassName // 通过类名获取多个元素,返回一个HTML Collection
document.getElementsByTagName // 通过标签名获取多个元素,返回一个HTML Collection
document.querySelector // 通过CSS选择器获取单个元素,返回第一个匹配的元素
doucment.querySelectorAll // 通过CSS选择器获取多个元素,返回一个NodeList
doucment.getElementsByName // 通过name属性获取多个元素,返回一个NodeList
4、script标签属性(defer/async及默认不写)都啥区别
script标签常用属性:src、type、async、defer、crossorigin、integrity、nomodule、
区别是加载和执行方式的不同。
async:异步加载,加载完成立即执行,执行顺序不保证(比如有多个async的脚本,取决于谁先加载完成)
defer:延迟加载,在文档中出现的顺序执行,在文档完全解析后执行,DOM完全构建后执行的脚本(特别依赖其他脚本的情况)
默认不写:同步加载和执行的,浏览器会在遇到 <script>
标签时停止解析文档,加载并执行该脚本,然后在继续解析文档,可能导致性能问题,尤其脚本较大或网络较慢时。
5、HTML存储方案
Cookies:存储小块数据,保存用户会话信息。限制在4KB左右,可以设置过期时间,过期后自动删除。
localStorage:长久存储数据,不会过期,需要手动删除。限制在4MB到10MB之间,取决于浏览器。需要同源下共享。数据持久化
sessionStorage:当前会话数据,关闭页面被清除。限制在5MB带10MB之间,仅在当前标签页或窗口有效,不能跨域。仅在会话有效
6、JS基本数据类型,symbol和bigint区别
number、string、boolean、null、undefined、Symbol、BigInt
Symbol:唯一性、不可枚举。用于创建唯一的标识符,避免属性名冲突,适合用于对象属性。
BigInt:不支持小数。用于表示任意精度的整数,适合需要处理大数的场景。
7、讲讲 var、let、const
var:函数作用域或全局作用域。函数内部声明,整个函数内有效;函数外部声明,在整个脚本中有效。
let:块级作用域,只在最近的块{}内有效。let在声明之前不能被访问,被称为“暂时性死区”。
const:块作用域,访问未声明的变量也受暂时性死区的影响。重点:const声明的是一个对象或数组,仍然可以修改其内容。
const c = 40;
// c = 50; // 报错:TypeError:Assignment to constant variable.
const obj = { key: 'value' };
obj.key = 'newValue'; // 这是合法的
console.log(obj.key); // 输出:newValue
8、0.1+0.2为什么不等于0.3
JavaScript使用IEEE754标准来表示浮点数,二进制形式存储。无法精确表示。
0.1和0.2的二进制表示为无限循环的小数,在计算机中只能近似存储,而不是精确存储。
解决方案:使用整数计算、使用toFixed()、使用第三方库。 0.30000000000000004
9、箭头函数和普通函数的区别
- 箭头函数是没有this;箭头函数中的this会指向外层作用域中this;
- 不可以作为构造函数,不能被new,因为箭头函数中不存在this指向;
- 箭头函数没有arguments
- 箭头函数不能使用yieId命令,不能作为Generator函数。
10、this
函数中的this,指的是当前函数的执行主体;谁让函数执行的,那么this就指向谁。
- 在
全局作用域
下,this指向window - 函数体中的this,看函数执行前有没有".",如果有,那么
点前面是谁,this就指向谁
;如果没有".",那么会指向window。 - 如果给
元素的事件行为绑定方法
,那么方法中的this,就会指向当前被绑定的哪个元素; 回调函数
中的this指向window;自执行函数
中的this永远指向window;构造函数
中的this,指向实例;call、apply、bind
可以改变this指向;
11、call、bind、apply
call: 调用函数并改变this值,逐个参数传递,立即执行
apply: 调用函数并改变this值,数组或者类数组,立即执行
bind: 创建一个新函数,逐个参数(可选),不会立即执行,返回一个新的函数
12、盒模型(两种)
Content+Padding+Border+margin
标准盒模型:总宽度= width + padding-left + padding-right + border-left + border-right
怪异盒模型:总宽度= width(不再加上内边距和边框的宽度)
box-sizing:border-box;这个时候盒子的宽度就包括内容宽度+左右padding+左右border
box-sizing:content-box不包括border和padding
13、垂直居中实现方式(六种)
/* Flexbox:简单常用 */
.container {
display: flex;
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
height: 100vh; /* 使容器充满视口高度 */
}
/* GridLayout:CSS Grid 实现垂直居中 */
.grid-container {
display: grid;
place-items: center; /* 同时实现水平和垂直居中 */
height: 100vh;
}
/* 绝对定位: 通过绝对定位和负边距实现垂直居中 */
.relative-container {
position: relative:
height: 100vh;
}
.absolute-content {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%); /* 平移自身宽高的一半 */
}
/* 表格布局:使用CSS表格布局的方式 */
.table-container {
display: table;
height: 100vh;
width: 100%; /* 或根据需要设置宽度 */
}
.table-cell {
display: table-cell;
vertical-align: middle; /* 垂直居中 */
text-align: center; /* 水平居中 */
}
/* 行内块元素: 使用行内块元素配合line-height属性 */
.inline-block-container {
height: 100vh;
text-align: center; /* 水平居中 */
}
.inline-block-content {
display: inline-block;
line-height: 100vh; /* 设置行高等于容器宽度 */
vertical-align: middle; /* 垂直居中 */
}
/* CSS变量和Calc():实现居中 */
.calc-container {
height: 100vh;
position: relative;
}
.calc-content {
position: absolute;
top: 50%;
left: 50%;
transform: tramslate(-50%, -50%);
/* 或者使用 calc() */
/* top: calc(50% - 0.5 * height); */
}
14、React中的虚拟DOM
是一种在内存中模拟真实DOM树的对象结构,用于描述用户界面。
虚拟DOM是对真实DOM的描述,它是一个JS对象,通过Babel转换成React.createElement()函数执行后生成的JS对象。
React使用虚拟DOM来减少对真实DOM的操作,从而提高应用的性能和响应速度。
工作原理:
- 创建和更新:当React组件的状态发生变化时,React会重新计算虚拟DOM树,生成一个新的虚拟DOM树。
- 比较和更新:React会比较新旧虚拟DOM树的差异,找出需要更新的部分
- 真实DOM更新:React会根据比较结果,高效地更新真实DOM,只更新那些实际发生变化的部分,而不是整个页面。
虚拟DOM的优势: - 性能优化:减少对真实DOM的操作次数,虚拟DOM可以显著提高应用的性能,减少重绘和回流的发生。
- 跨平台开发:由于虚拟DOM是一个抽象层,React可以更容易地实现跨平台开发,例如将应用部署到web、ios和android等不同平台。
- 组件化开发:虚拟DOM支持组件化开发,使得代码更加模块化,易于维护和扩展。
15、高阶组件(HOC,Higher-Order Component)
定义:高阶组件是一个函数,它接受一个组件作为参数,并返回一个新的组件。HOC用于复用组件逻辑和功能。
注意事项:
- 不要修改原组件: 高阶组件应当不直接修改传入的组件,而是返回一个新的组件。这有助于保持组件的可复用性和可维护性。
- 静态方法:如果原组件有静态方法,使用hoist-non-react-statice库可以将这些静态方法复制到高阶组件中。
- 命名:高阶组件通常以with前缀命名,以便于识别,例如withLogging,withAuth等。
- 性能考虑:高阶组件会增加组件树的复杂性,过多的高阶组件可能会影响性能,需谨慎使用。
16、React组件通信的方式
- 父子组件通信
- 通过props传递数据:父组件可以通过props向子组件传递数据和回调函数
- 通过回调函数传递数据:父组件可以将回调函数作为props传递给子组件,子组件可以调用这个函数将数据传回父组件。
- 兄弟组件通信
- 提升状态:通过将共享状态提升到它们的共同父组件,兄弟组件可以通过父组件的props进行通信。
- 通过Context API:React的Context API提供了一种在组件树中传递数据的方法,而不必通过每个组件的props逐层传递。
- 使用状态管理库:对于更复杂的应用,使用状态管理库(如Redux、Mobx、Recoil等)可以简化组件之间的通信。
- 使用Redux
17、常用打包工具
webpack:强大的模块打包工具。支持 代码分割、懒加载】热模块替换;通过加载器(Loaders)处理不同类型的文件;插件系统(Plugins)可以扩展功能,如压缩代码、生成HTML文件等
Parcel:零配置的打包工具,适合快速开发。
Rollup:打包JavaScript库的工具,特别适合ES6模块。
Vite:新兴的前端构建工具,强调快速开发和即时反馈。
Browserify:将Node.js风格的模块打包为浏览器可用的工具。
Gulp:基于流的构建工具,常用于自动化构建和任务管理。
Grunt:自订花构建工具,使用配置文件定义任务。
Next.js和Nuxt.js:基于React和Vue的框架,内置了打包的构建工具。
Snowpack:快速的前端构建工具,基于ES模块。
18、webpack工作原理
- 模块化
- 入口(Entry)
- 依赖图(Dependency Graph)
- 加载器(Loaders)
- 插件(Plugins)
- 打包(Bunding)
- 开发模式与生产模式
- 热模块替换(HMR)
工作原理分为几步骤
1、从入口文件开始构建依赖图,找到所有依赖的模块。
2、使用加载器处理各种资源,将它们转换为有效的模块。
3、使用插件扩展功能,优化打包过程。
4、将所有模块打包成一个或多个输出文件,供浏览器使用。
19、loader和plugin的区别
loader:转换文件内容,处理单个模块;主要针对单个文件或模块;在module.rules中定义;按照规则链式调用
plugin:执行构建过程中的各种任务,影响整体构建;影响整个构建过程;在plugins数组中定义;在特定的构建生命周期阶段执行
20、webpack打包优化处理方式
- 代码拆分(Code Splitting ):将代码拆分为多个较小的包,Webpack可以按需加载这些包,减少初始加载时间。「动态导入,使用sptimization.splitChunks」
- 树摇(Tree Shaking):去除未使用代码的过程,确保使用mode:‘production’,并使用ES6的import和export。
- 压缩和混淆代码:使用插件压缩和混淆代码以减少文件体积。
- 优化图片和资源:使用loader来优化图像和资源的加载。
- 使用缓存:利用浏览器缓存和Webpack的缓存机制来减少构建时间。
- 减少依赖:使用resolve.alias:通过配置别名来避免重复导入;移除不必要的依赖:定期检查项目依赖,移除未使用的库。
- 使用CDN:将一些常用库(如React、Vue)通过CDN引入,减少打包体积。
- 启用Gzip压缩:通过服务器启用Gzip压缩,可以减少传输文件的体积。
- 使用PWA(渐进式Web应用):通过Service Workers 和缓存策略,提升应用性能和用户体验。
- 分析打包结果:使用插件分析打包结果,以了解包的结构和大小。