2023前端面试题

1.什么是重绘和回流,有哪些措施可以避免回流,从而提高页面性能

重绘(repaint)和回流(reflow)是浏览器渲染页面时的两个重要的步骤。

重绘是指当一个元素的样式(如颜色、背景等)发生变化,但没有影响其布局(如位置、大小等)时,浏览器会将这个元素的新样式重新画到页面上。

回流则是指当一个元素的布局发生变化时,浏览器需要重新计算该元素在页面中的位置和大小,并且需要重新布局相关元素,这个过程可能会导致整个页面其他部分的重新渲染。

由于回流会涉及到多个元素的重新计算和布局,因此它的成本要比重绘更高,会对页面性能产生较大的影响。

为了避免回流,可以采取以下几个措施:

  1. 减少 DOM 操作:DOM 的增删改操作会引起回流,因此尽量减少这些操作,可以通过使用文档碎片、虚拟 DOM 等技术来优化。

  2. 使用 CSS3 动画代替 JavaScript 动画:CSS3 动画由浏览器自己处理,不会触发 JavaScript 脚本,因此可以避免回流。

  3. 避免频繁读取 offsetLeft、offsetTop 等属性:这些属性的读取会导致回流,如果需要多次读取,可以将其缓存起来。

  4. 使用 transform 和 opacity 属性:这两个属性不会触发回流,可以用来实现元素的动画效果。

  5. 避免使用 table 布局:table 的布局方式比较复杂,可能会导致频繁的回流,可以使用 div 布局代替。

通过上述措施的实践,可以显著提高页面性能,使用户的体验更加流畅和舒适。

2.什么是 BFC

BFC(块级格式化上下文)是前端开发中的一个重要概念,它是指一个独立的渲染区域,规定了内部元素如何布局,并且与外部元素互相隔离。在一个BFC中,所有的子元素会根据一定的规则进行布局,这些规则包括:浮动、清除浮动、尺寸计算、边距折叠等。

前端BFC可以解决一些常见的布局问题,例如:父容器和子元素之间的margin折叠问题、浮动元素造成的高度塌陷问题等。通过创建一个BFC,我们可以让元素具有一定的独立性,从而实现更加灵活的布局。

在HTML中,可以通过以下方式来创建一个BFC:

  1. float属性不为none;
  2. position属性为absolute或fixed;
  3. display属性为inline-block、table-cell、table-caption;
  4. overflow属性不为visible。

值得注意的是,创建BFC的元素之间也不会影响彼此的布局,因此在设计复杂页面时,合理利用BFC可以帮助我们简化布局,提高开发效率。

3.vue 实现数据绑定以及页面dom更新机制

Vue实现数据绑定和页面DOM更新的机制,主要依靠响应式系统和虚拟DOM技术。

  1. 响应式系统

Vue使用了一种称为响应式系统的观察者模式来监听数据的变化。当一个组件实例创建时,Vue会遍历data选项中的属性,对每个属性都使用Object.defineProperty方法将其转化为getter/setter,并且在内部建立一个依赖收集器(Dep),用来收集当前属性的所有订阅者(Watcher)。

当数据发生改变时,setter就会被调用,setter会通知依赖收集器向订阅该属性的所有Watcher发送通知,告诉它们数据已经发生了变化。Watcher接收到通知后,会重新计算表达式的值,并且更新视图。

  1. 虚拟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变化)   
      node的事件循环分为 6 个阶段
      浏览器和 Node 环境下,microtask 任务队列的执行时机不同 Node 端,
       microtask(微任务) 在事件循环的各个阶段之间执行 浏览器端,
       microtask 在事件循环的 macrotask 执行完之后执行
6.什么是闭包,闭包的使用场景
  JavaScript闭包(closure)是指一个函数可以访问其外部作用域的变量。具体来说,当一个函数在内部定义了另一个函数,内部函数可以访问外部函数的变量和参数,即使外部函数已经返回。这样        的函数组合形成了闭包。 闭包有很多使用场景,其中一种常见的例子是使用闭包创建私有变量。在JavaScript中,没有真正的私有变量,但是通过使用闭包,可以模拟出类似于私有变量的效果。
7.原生js的事件监听
  标签中的onxxx,比如<button οnclick="btnHandler">按钮</button>

  js中的onxxx,比如document.body.onclick = function() { /* body click */ }
  js中的addEventListener,比如document.body.addEventListener("click", () => { /* body click */ },useCapture)

  useCapture可选。布尔值,指定事件是否在捕获或冒泡阶段执行。

  • true - 事件句柄在捕获阶段执行,
  • false- false- 默认。事件句柄在冒泡阶段执行
8.防抖和节流
节流
function throttle(fn, time) {
    let timer
    return function () {
        if(!timer) {
            timer = setTimeout(()=>{
                fn.apply(this, arguments)
                timer = null
            }, time)
        }
    }
}
防抖
function debounce(fn,time) {
    let timer
    return function () {
        if(timer) clearTimeout(timer)

        timer = setTimeout(
    ()=>{
                fn.apply(this, arguments)
            }
,time)
    }
}
function debounce(fn,time) {
    let timer
    return function () {
        if(!timer || new Date() - timer > time) {
            fn.apply(this, arguments)
            timer = new Date()
        }
    }
}
9.new 一个构造函数的过程
  1. 创建一个空对象。
  2. 将这个新对象的原型指向构造函数的prototype属性。
  3. 执行构造函数,并且将this指向新创建的对象。
  4. 如果构造函数没有返回值或者返回一个非对象值,则返回新创建的对象。如果构造函数返回一个对象,则返回这个对象。
10.vue3的组合API和react的hook的区别

Vue 3 的组合 API 和 React 的 Hook 都是为了解决在函数式编程中,复用逻辑的问题。它们的主要区别在于以下几点:

  1. 调用方式不同

Vue 3 的组合 API 是通过在 setup 函数中定义和调用,而 React 的 Hook 是通过在函数组件中定义和调用。

  1. 使用方式不同

Vue 3 的组合 API 主要是通过提供一些可以重用的函数,让用户自由组合来实现不同的逻辑。而 React 的 Hook 则是通过使用钩子函数来扩展函数组件的功能和状态。

  1. 状态管理方式不同

Vue 3 的组合 API 主要是通过 reactive 和 ref 来管理状态,而 React 的 Hook 则是通过 useState 和 useReducer 来管理状态。

  1. 生命周期不同

Vue 3 的组合 API 中没有明确的生命周期函数,而 React 的 Hook 则有一些生命周期相关的钩子函数,比如 useEffect。

总的来说,Vue 3 的组合 API 和 React 的 Hook 都是为了解决在函数式编程中,复用逻辑的问题,但是使用方式和具体的实现细节还是有所差异。如果你熟悉其中的一种,那么学习另外一种也相对容易些

11.webpack工作原理及loader和plugin的区别

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属性。
13.盒模型
盒模型(Box Model)是CSS中一个非常重要的概念,它描述了一个HTML元素在页面中所占据的空间大小。每个HTML元素都可以看作是一个矩形盒子,由四个部分组成:内容区域(Content)、内边距(Padding)、边框(Border)和外边距(Margin)。这四个部分的大小和样式可以通过CSS来进行控制。
。在CSS中,我们可以通过box-sizing属性来控制盒模型的计算方式,包括content-box(默认值,表示盒模型的大小只包括内容区域)、padding-box(表示盒模型的大小包括内容区域和内边距)和border-box(表示盒模型的大小包括内容区域、内边距和边框)。
  1. 标准盒模型:也被称为W3C盒模型,元素的width和height只包括内容的宽和高,不包括边框(border)和内边距(padding)

  2. IE盒模型:又被称为传统盒模型或者怪异盒模型,但是IE盒模型的content部分包含了padding和border

  3. 新盒模型:由于标准盒模型和IE盒模型各有优缺点,因此一些浏览器厂商提出了新盒模型,它是一种在标准盒模型的基础上增加了box-sizing属性来控制元素的盒模型类型的方式。当box-sizing为border-box时,元素的总宽度和高度包括了内边距、边框和内容区域,但不包括外边距;当box-sizing为content-box时,元素的总宽度和高度仅包括内容区域,不包括内边距、边框和外边距。

14.水平垂直居中

.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%);

}

15.flex左侧固定宽度右侧自适应

.container {
display: flex;
align-items: center;
}

.left {
width: /* 左侧固定宽度 */;
}

.right {
flex: 1;
}

16.深拷贝
function deepClone(obj) {
    if(typeof obj !== 'object' || obj===null) {
        return obj
    }
    const res = Array.isArray(obj)?[]:{}

    for (const key in obj) {
        if (obj.hasOwnProperty(key)) {
            res[key] = deepClone(obj[key])
        }
    }
    return res
}
17.react生命周期

1.组件将要挂载时触发的函数: componentWillMount

2.组件挂载完成时触发的函数: componentDidMount

3.是否要更新数据时触发的函数: shouldComponentUpdate

4.将要更新数据时触发的函数: componentWillUpdate

5.数据更新完成时触发的函数: componentDidUpdate

6.组件将要销毁时触发的函数: componentWillUnmount
7.父组件中改变了props传值时触发的函数: componentWillReceiveProps

 
18.虚拟dom

虚拟 DOM (Virtual DOM) 是将整个页面抽象成一个虚拟的树形结构,通过对这个数据结构的操作来实现对页面的更新和渲染。虚拟 DOM 的实现方法是在浏览器中创建一个轻量级的 JavaScript 对象来描述页面的结构,每当数据发生变化时,就会重新生成一个新的虚拟 DOM,并与旧的虚拟 DOM 进行比较,找出两者之间的差异,最后只更新真正需要改变的部分。

虚拟 DOM 的主要作用包括:

  1. 提高性能:由于直接操作真实 DOM 会涉及到重新计算布局、绘制等复杂操作,所以使用虚拟 DOM 可以有效减少这些操作,提高页面的性能。
  2. 方便跨平台开发:由于虚拟 DOM 是基于 JavaScript 实现的,所以可以方便地在不同的平台上使用相同的代码进行开发。
  3. 方便开发和维护:通过使用虚拟 DOM,开发人员可以更加方便地管理页面的状态和结构,降低了复杂度,同时也方便了维护和测试。

虚拟 DOM 的实现方法一般是通过使用 React、Vue 等框架来实现的。这些框架提供了一套完整的组件化开发方案,将整个页面抽象为不同的组件,通过对组件状态和事件的管理来实现虚拟 DOM 的更新和渲染。

19.缓存
  1. 强缓存:强制浏览器在一定时间内直接从本地缓存读取数据,不向服务器发送请求。强缓存可以通过设置响应头信息实现,常见的响应头有 Expires 和 Cache-Control
  2. 协商缓存:在强缓存失效时,浏览器会向服务器发送请求,询问服务器该资源在最后一次访问后是否有修改。如果没有修改,服务器会返回 304 状态码,告诉浏览器可以继续使用本地缓存,否则会返回新的资源内容。协商缓存可以通过设置响应头信息实现,常见的响应头有 Last-Modified 和 ETag
  3. 浏览器缓存的主要流程可以概括为以下几个步骤:

    1. 浏览器收到 HTTP 请求时,会根据 URL 判断该资源是否已经被缓存。如果已经被缓存,则直接从本地缓存读取资源。
    2. 如果未被缓存或者缓存已经过期,浏览器会向服务器发送请求,并在请求中带上一些信息,例如上次访问时间、Etag 等。
    3. 服务器收到请求后,根据请求中的信息判断资源是否有更新。如果资源没有更新,则返回一个 304 响应码,告诉浏览器可以继续使用本地缓存;如果资源已经更新,则返回新的资源内容和一些缓存相关的头信息。
    4. 浏览器收到响应后,会根据响应头信息来更新本地缓存,并将新的资源内容展示给用户
20.Jenkins
21.vue生命周期
  1. beforeCreate():在实例初始化之后,数据观测(data observer) 和 event/watcher 事件配置之前被调用。

  2. created():在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算,event/watcher 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。

  3. beforeMount():在挂载开始之前被调用,在 render 函数被调用时,但是在实际渲染之前。该钩子在服务器渲染期间不被调用。

  4. mounted():实例挂载后被调用,这时 el 被新创建的 vm.��替换了。如果根实例挂载到了一个文档内的元素上,当�������被调用时��.el替换了。如果根实例挂载到了一个文档内的元素上,当mounted被调用时vm.el 也在文档内。

  5. beforeUpdate():数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。

  6. updated():由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。当这个钩子被调用时,组件的 DOM 已经更新。

  7. beforeDestroy():实例销毁之前调用。在这一步,实例仍然完全可用。

  8. destroyed():实例销毁之后调用。这个钩子被调用之后,Vue 实例中的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。

  9. activated():在<keep-alive>组件激活时调用。

  10. deactivated():在<keep-alive>组件停用时调用

 
22.跨域

跨域是指访问一个不同于当前页面所在域名、协议或端口的资源。常见的跨域问题包括 Ajax 请求、跨域写入 Cookie 等。

解决跨域问题的一些方法包括:

  1. JSONP:通过动态生成 script 标签,实现跨域获取数据。
  2. CORS:在服务器端设置 Access-Control-Allow-Origin 头信息,允许其他域名的请求。
  3. 代理:通过在自己的服务器上设置代理,实现对其他域名的请求转发。
  4. WebSocket:使用 WebSocket 协议进行通信,WebSocket 不受同源策略限制。
posted @ 2023-05-08 09:23  刘兵博客  阅读(1117)  评论(1编辑  收藏  举报