2023前端面试题
1.什么是重绘和回流,有哪些措施可以避免回流,从而提高页面性能
重绘(repaint)和回流(reflow)是浏览器渲染页面时的两个重要的步骤。
重绘是指当一个元素的样式(如颜色、背景等)发生变化,但没有影响其布局(如位置、大小等)时,浏览器会将这个元素的新样式重新画到页面上。
回流则是指当一个元素的布局发生变化时,浏览器需要重新计算该元素在页面中的位置和大小,并且需要重新布局相关元素,这个过程可能会导致整个页面其他部分的重新渲染。
由于回流会涉及到多个元素的重新计算和布局,因此它的成本要比重绘更高,会对页面性能产生较大的影响。
为了避免回流,可以采取以下几个措施:
-
减少 DOM 操作:DOM 的增删改操作会引起回流,因此尽量减少这些操作,可以通过使用文档碎片、虚拟 DOM 等技术来优化。
-
使用 CSS3 动画代替 JavaScript 动画:CSS3 动画由浏览器自己处理,不会触发 JavaScript 脚本,因此可以避免回流。
-
避免频繁读取 offsetLeft、offsetTop 等属性:这些属性的读取会导致回流,如果需要多次读取,可以将其缓存起来。
-
使用 transform 和 opacity 属性:这两个属性不会触发回流,可以用来实现元素的动画效果。
-
避免使用 table 布局:table 的布局方式比较复杂,可能会导致频繁的回流,可以使用 div 布局代替。
通过上述措施的实践,可以显著提高页面性能,使用户的体验更加流畅和舒适。
2.什么是 BFC
BFC(块级格式化上下文)是前端开发中的一个重要概念,它是指一个独立的渲染区域,规定了内部元素如何布局,并且与外部元素互相隔离。在一个BFC中,所有的子元素会根据一定的规则进行布局,这些规则包括:浮动、清除浮动、尺寸计算、边距折叠等。
前端BFC可以解决一些常见的布局问题,例如:父容器和子元素之间的margin折叠问题、浮动元素造成的高度塌陷问题等。通过创建一个BFC,我们可以让元素具有一定的独立性,从而实现更加灵活的布局。
在HTML中,可以通过以下方式来创建一个BFC:
- float属性不为none;
- position属性为absolute或fixed;
- display属性为inline-block、table-cell、table-caption;
- overflow属性不为visible。
值得注意的是,创建BFC的元素之间也不会影响彼此的布局,因此在设计复杂页面时,合理利用BFC可以帮助我们简化布局,提高开发效率。
3.vue 实现数据绑定以及页面dom更新机制
Vue实现数据绑定和页面DOM更新的机制,主要依靠响应式系统和虚拟DOM技术。
- 响应式系统
Vue使用了一种称为响应式系统的观察者模式来监听数据的变化。当一个组件实例创建时,Vue会遍历data选项中的属性,对每个属性都使用Object.defineProperty方法将其转化为getter/setter,并且在内部建立一个依赖收集器(Dep),用来收集当前属性的所有订阅者(Watcher)。
当数据发生改变时,setter就会被调用,setter会通知依赖收集器向订阅该属性的所有Watcher发送通知,告诉它们数据已经发生了变化。Watcher接收到通知后,会重新计算表达式的值,并且更新视图。
- 虚拟DOM技术
Vue使用了虚拟DOM技术来优化DOM操作。当组件的数据发生变化,Vue会先将数据转换为虚拟DOM对象,并将其与上一次渲染的虚拟DOM进行比较,得出需要更新的部分,然后只更新这些部分的真实DOM,而不是全部重新渲染整个组件。这样可以减少DOM操作的次数,提高性能。
总的来说,Vue的数据绑定和DOM更新机制是通过响应式系统和虚拟DOM技术相结合来实现的。通过响应式系统,Vue能够监听数据变化并自动更新视图,而虚拟DOM技术可以优化DOM操作,提高性能。
4.什么是js原型链
JavaScript中的每个对象都有一个原型,也就是它们继承属性和方法的对象。而这个原型又可以有自己的原型,形成了所谓的“原型链”。
当我们访问一个JavaScript对象的属性或方法时,首先会在该对象本身查找是否存在该属性或方法。如果不存在,它会沿着该对象的原型链向上查找,一直到Object.prototype为止。如果还没有找到,则返回undefined。
因此,通过原型链,我们可以实现继承和代码复用。例如,我们可以创建一个基础对象,并将其作为其他对象的原型,使得后者能够共享基础对象的属性和方法。
5.js中event loop,以及浏览器和node的event loop的异同
- 代码开始执行,创建一个全局调用栈,
script
作为宏任务执行 - 执行过程过同步任务立即执行,异步任务根据异步任务类型分别注册到微任务队列和宏任务队列
- 同步任务执行完毕,查看微任务队列
- 若存在微任务,将微任务队列全部执行(包括执行微任务过程中产生的新微任务)
- 若无微任务,查看宏任务队列,执行第一个宏任务,宏任务执行完毕,查看微任务队列,重复上述操作,直至宏任务队列为空
- 宏任务(script、定时器、ajax、I/O);微任务(promise.then、async await、MutationObserve 监听dom变化)
js中的onxxx,比如document.body.onclick = function() { /* body click */ }
js中的addEventListener,比如document.body.addEventListener("click", () => { /* body click */ },useCapture)
useCapture可选。布尔值,指定事件是否在捕获或冒泡阶段执行。
- true - 事件句柄在捕获阶段执行,
- false- false- 默认。事件句柄在冒泡阶段执行
- 创建一个空对象。
- 将这个新对象的原型指向构造函数的prototype属性。
- 执行构造函数,并且将this指向新创建的对象。
- 如果构造函数没有返回值或者返回一个非对象值,则返回新创建的对象。如果构造函数返回一个对象,则返回这个对象。
Vue 3 的组合 API 和 React 的 Hook 都是为了解决在函数式编程中,复用逻辑的问题。它们的主要区别在于以下几点:
- 调用方式不同
Vue 3 的组合 API 是通过在 setup 函数中定义和调用,而 React 的 Hook 是通过在函数组件中定义和调用。
- 使用方式不同
Vue 3 的组合 API 主要是通过提供一些可以重用的函数,让用户自由组合来实现不同的逻辑。而 React 的 Hook 则是通过使用钩子函数来扩展函数组件的功能和状态。
- 状态管理方式不同
Vue 3 的组合 API 主要是通过 reactive 和 ref 来管理状态,而 React 的 Hook 则是通过 useState 和 useReducer 来管理状态。
- 生命周期不同
Vue 3 的组合 API 中没有明确的生命周期函数,而 React 的 Hook 则有一些生命周期相关的钩子函数,比如 useEffect。
总的来说,Vue 3 的组合 API 和 React 的 Hook 都是为了解决在函数式编程中,复用逻辑的问题,但是使用方式和具体的实现细节还是有所差异。如果你熟悉其中的一种,那么学习另外一种也相对容易些
Webpack是一款现代化的静态模块打包工具,主要用于前端开发中的资源打包、代码转换、文件优化和模块管理等方面。其主要工作原理是通过对项目中各个模块之间依赖关系的分析,将所有模块及其相关依赖打包成一个或多个最终可执行的静态资源。 在Webpack的构建过程中,常会使用Loader和Plugin两种不同的机制对模块进行处理和扩展。 Loader是用于对某些特定类型的模块进行特定的转换处理,例如将ES6语法转换为ES5语法、将CSS文件转换为JavaScript模块等。Loader有点像一种转换器,可以将需要处理的模块转换为Webpack可以识别的标准格式,然后进行下一步的打包处理。 Plugin则是用于实现Webpack打包流程中的各种自动化任务和功能扩展,例如打包文件压缩、文件复制、版本控制、环境变量注入等。Plugin可以在Webpack的构建过程中插入钩子(hooks),并基于这些钩子实现各种操作和功能扩展。 总体来说,Loader和Plugin都是Webpack中非常重要的概念,Loader通过模块转换实现对代码的修改和增强,Plugin则通过Webpack生命周期的钩子实现对Webpack构建流程的扩展和定制。
12.flex布局Flex容器常用的属性包括:
- flex-direction:用来设置Flex容器内部Flex项目的排列方向(主轴线的方向),可以设置成row(从左到右排列)、column(从上到下排列)、row-reverse(从右到左排列)和column-reverse(从下到上排列)。
- justify-content:用来设置Flex项目在主轴线上的对齐方式,可以设置成flex-start(从起点开始排列)、flex-end(从终点结束排列)、center(居中排列)、space-between(两端对齐,项目之间的间隔相等)和space-around(每个项目周围都有相等的间隔)。
- align-items:用来设置Flex项目在交叉轴线上的对齐方式,可以设置成flex-start(靠近交叉轴线起点排列)、flex-end(靠近交叉轴线终点排列)、center(居中排列)、baseline(基线对齐)和stretch(拉伸填满容器)。
Flex子元素常用的属性包括:
- flex:用来设置Flex子元素的尺寸大小和比例关系,可以设置成一个数字,代表它在所有Flex项目中所占的比例。
- order:用来设置Flex子元素在Flex容器内的排序位置,数值越小,排列越靠前。
- align-self:用来设置Flex子元素在交叉轴线上的对齐方式,可以覆盖父容器的align-items属性。
-
标准盒模型:也被称为W3C盒模型,元素的width和height只包括内容的宽和高,不包括边框(border)和内边距(padding)
-
IE盒模型:又被称为传统盒模型或者怪异盒模型,但是IE盒模型的content部分包含了padding和border
-
新盒模型:由于标准盒模型和IE盒模型各有优缺点,因此一些浏览器厂商提出了新盒模型,它是一种在标准盒模型的基础上增加了box-sizing属性来控制元素的盒模型类型的方式。当box-sizing为border-box时,元素的总宽度和高度包括了内边距、边框和内容区域,但不包括外边距;当box-sizing为content-box时,元素的总宽度和高度仅包括内容区域,不包括内边距、边框和外边距。
.container {
display: flex;
justify-content: center;
align-items: center;
}
.container {
display: grid;
place-items: center;
}
.container { position: relative; }
.child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.container {
display: flex;
align-items: center;
}
.left {
width: /* 左侧固定宽度 */;
}
.right {
flex: 1;
}
1.组件将要挂载时触发的函数: componentWillMount
2.组件挂载完成时触发的函数: componentDidMount
3.是否要更新数据时触发的函数: shouldComponentUpdate
4.将要更新数据时触发的函数: componentWillUpdate
5.数据更新完成时触发的函数: componentDidUpdate
6.组件将要销毁时触发的函数: componentWillUnmount
7.父组件中改变了props传值时触发的函数: componentWillReceiveProps
虚拟 DOM (Virtual DOM) 是将整个页面抽象成一个虚拟的树形结构,通过对这个数据结构的操作来实现对页面的更新和渲染。虚拟 DOM 的实现方法是在浏览器中创建一个轻量级的 JavaScript 对象来描述页面的结构,每当数据发生变化时,就会重新生成一个新的虚拟 DOM,并与旧的虚拟 DOM 进行比较,找出两者之间的差异,最后只更新真正需要改变的部分。
虚拟 DOM 的主要作用包括:
- 提高性能:由于直接操作真实 DOM 会涉及到重新计算布局、绘制等复杂操作,所以使用虚拟 DOM 可以有效减少这些操作,提高页面的性能。
- 方便跨平台开发:由于虚拟 DOM 是基于 JavaScript 实现的,所以可以方便地在不同的平台上使用相同的代码进行开发。
- 方便开发和维护:通过使用虚拟 DOM,开发人员可以更加方便地管理页面的状态和结构,降低了复杂度,同时也方便了维护和测试。
虚拟 DOM 的实现方法一般是通过使用 React、Vue 等框架来实现的。这些框架提供了一套完整的组件化开发方案,将整个页面抽象为不同的组件,通过对组件状态和事件的管理来实现虚拟 DOM 的更新和渲染。
- 强缓存:强制浏览器在一定时间内直接从本地缓存读取数据,不向服务器发送请求。强缓存可以通过设置响应头信息实现,常见的响应头有
Expires
和Cache-Control
。 - 协商缓存:在强缓存失效时,浏览器会向服务器发送请求,询问服务器该资源在最后一次访问后是否有修改。如果没有修改,服务器会返回 304 状态码,告诉浏览器可以继续使用本地缓存,否则会返回新的资源内容。协商缓存可以通过设置响应头信息实现,常见的响应头有
Last-Modified
和ETag
。 -
浏览器缓存的主要流程可以概括为以下几个步骤:
- 浏览器收到 HTTP 请求时,会根据 URL 判断该资源是否已经被缓存。如果已经被缓存,则直接从本地缓存读取资源。
- 如果未被缓存或者缓存已经过期,浏览器会向服务器发送请求,并在请求中带上一些信息,例如上次访问时间、Etag 等。
- 服务器收到请求后,根据请求中的信息判断资源是否有更新。如果资源没有更新,则返回一个 304 响应码,告诉浏览器可以继续使用本地缓存;如果资源已经更新,则返回新的资源内容和一些缓存相关的头信息。
- 浏览器收到响应后,会根据响应头信息来更新本地缓存,并将新的资源内容展示给用户
-
beforeCreate()
:在实例初始化之后,数据观测(data observer) 和 event/watcher 事件配置之前被调用。 -
created()
:在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算,event/watcher 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。 -
beforeMount()
:在挂载开始之前被调用,在 render 函数被调用时,但是在实际渲染之前。该钩子在服务器渲染期间不被调用。 -
mounted()
:实例挂载后被调用,这时 el 被新创建的 vm.��替换了。如果根实例挂载到了一个文档内的元素上,当�������被调用时��.el替换了。如果根实例挂载到了一个文档内的元素上,当mounted被调用时vm.el 也在文档内。 -
beforeUpdate()
:数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。 -
updated()
:由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。当这个钩子被调用时,组件的 DOM 已经更新。 -
beforeDestroy()
:实例销毁之前调用。在这一步,实例仍然完全可用。 -
destroyed()
:实例销毁之后调用。这个钩子被调用之后,Vue 实例中的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。 -
activated()
:在<keep-alive>组件激活时调用。 -
deactivated()
:在<keep-alive>组件停用时调用
跨域是指访问一个不同于当前页面所在域名、协议或端口的资源。常见的跨域问题包括 Ajax 请求、跨域写入 Cookie 等。
解决跨域问题的一些方法包括:
- JSONP:通过动态生成 script 标签,实现跨域获取数据。
- CORS:在服务器端设置 Access-Control-Allow-Origin 头信息,允许其他域名的请求。
- 代理:通过在自己的服务器上设置代理,实现对其他域名的请求转发。
- WebSocket:使用 WebSocket 协议进行通信,WebSocket 不受同源策略限制。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
2021-05-08 linux命令
2018-05-08 vue-cli本地环境API代理设置和解决跨域