前端面试题10

本文探讨了CSS中的BFC概念、前端处理大量数据的策略、CSS函数、JavaScript操作DOM的方法、Vue中监听对象变化、堆栈与栈的区别、单页应用SPAs的优缺点、MVVM模式以及JavaScript的类型转换和获取对象原型的方法。
摘要由CSDN通过智能技术生成

81、什么是BFC

BFC(Block Formatting Context)是CSS布局中一个非常重要的概念,它是由W3C CSS 2.1规范定义的一种布局模型或渲染机制。BFC可以理解为一个独立的渲染区域或者说是一个隔离了的布局环境,在这个环境中,其内部元素的布局不会受到外界的影响,并且遵循一套内部特有的布局规则。

具体来说,当一个元素生成了BFC时,该元素内部的块级盒子会按照一定规则进行布局:

  1. 垂直方向上的布局:BFC中的块盒会在垂直方向上一个接一个地放置,彼此之间的margin会发生折叠(仅限相邻垂直margin),而且每个盒子的顶部始于包含块的顶部,底部则根据其内容和高度计算结束位置。
  2. 浮动元素包含:BFC可以包含其内部的所有浮动元素,即使这些浮动元素浮动出了BFC之外,也不会影响到BFC外部元素的布局。
  3. 外边距重叠消除:BFC可以阻止其内部元素的垂直外边距发生折叠,这对于防止外边距塌陷很有帮助。
  4. 内部绝对定位:BFC中绝对定位元素的位置计算也会受到这个区域的限制。

以下情况会触发BFC的创建:

  • 根元素 <html>
  • float属性不为none的元素
  • position值为absolutefixed的元素
  • display属性值为inline-block, table-cell, table-caption, flex, 或 inline-flex的元素
  • overflow值不是visible的元素(如:overflowautoscrollhidden

BFC在解决布局问题中扮演着关键角色,例如清除浮动、防止外边距折叠、保持多列布局的边界独立等。通过理解和应用BFC,开发者能够更好地控制页面布局行为。

82、前端如何处理大量数据

前端处理大量数据时,需要考虑的主要问题是性能优化以及用户体验。以下是一些有效的策略和方法:

  1. 分页
    • 对于列表类数据,最常用的策略是分页加载,只显示当前页面的数据,当用户滚动到底部时,通过AJAX异步加载下一页数据,这样避免了一次性加载所有数据导致页面卡顿或内存溢出。
  2. 无限滚动(Infinite Scroll / 懒加载)
    • 类似于分页,但更加流畅,当用户滚动到视窗底部时自动加载更多的数据,保持用户体验的同时降低一次性加载的压力。
  3. 虚拟滚动(Virtual Scrolling)
    • 只渲染可视区域内的DOM节点,滚动时动态计算应该显示的数据部分并实时更新DOM,显著减少DOM节点数量。
  4. 数据分段处理
    • 将大数据集分割成小块,每次只处理和渲染一小部分数据,可以使用createDocumentFragment()来创建DOM片段,然后一次性将片段插入到DOM树中,减少渲染次数。
  5. 服务端/客户端过滤与排序
    • 在请求数据时就由服务器预先处理好分页、过滤和排序,减轻客户端负担;也可以在客户端处理,但要注意性能开销。
  6. 缓存和复用
    • 对于重复使用的数据,可以采用LRU(最近最少使用)缓存策略,将已加载过的数据缓存在内存中,减少不必要的网络请求。
  7. 数据预处理与压缩传输
    • 后端可以对数据进行压缩,前端接收后再解压,减少网络传输时间和带宽占用。
  8. 图表组件优化
    • 如果数据用于图表展示,可以选择高效的图表库,支持大数据量下的动态渲染和缩放,如Highcharts、ECharts等,它们通常自带大数据量的处理机制。
  9. Web Worker
    • 使用Web Worker进行复杂的计算任务,将CPU密集型工作转移到后台线程中,避免阻塞主线程,影响页面响应。
  10. React/Vue/Angular等框架的优化
    • 利用现代前端框架的虚拟DOM特性,结合shouldComponentUpdate生命周期钩子函数或React.memo、Vue的computed属性等机制,确保只有状态变化的部分重新渲染。

总之,前端处理大量数据的核心思想是尽可能减少DOM操作,合理分配计算资源,并结合合理的网络策略,使得数据加载和渲染过程平滑且不影响用户体验。

83、CSS函数有哪些

CSS 中有许多内置函数,它们用于处理颜色、尺寸、形状、渐变以及其他各种样式效果。以下是一些常见的CSS函数:

  1. 颜色处理函数
    • rgb(), rgba():基于红绿蓝三原色及可选透明度创建颜色。
    • hsl(), hsla():基于色相、饱和度、亮度及可选透明度创建颜色。
    • color()(CSS Color Module Level 4):兼容多种颜色格式。
    • currentColor:引用元素当前的字体颜色。
    • var():使用CSS变量创建颜色或其他值。
  2. 尺寸和单位转换函数
    • calc():计算长度、频率、角度、时间、百分比、数值等值。
    • clamp()(CSS Values and Units Module Level 4):限制值在指定的最小值和最大值之间。
    • min()max():取多个值中的最小值或最大值作为最终计算结果。
  3. 滤镜和图像处理函数
    • blur(), brightness(), contrast(), grayscale(), hue-rotate(), invert(), opacity(), saturate(), sepia():CSS滤镜函数,用于调整图像效果。
    • drop-shadow():添加阴影效果给元素。
    • url():引入外部资源,如背景图片。
  4. 渐变函数
    • linear-gradient():创建线性渐变背景。
    • radial-gradient():创建径向渐变背景。
    • conic-gradient()(CSS Images Module Level 4):创建锥形渐变背景。
  5. 几何函数
    • repeat()spaceroundno-repeat 等关键字配合 background-repeatbackground-size 属性创建背景图的重复模式。
    • containcover 关键字配合 background-size 创建适应容器的背景图片大小。
  6. 其他函数
    • attr():获取HTML元素的属性值并应用于CSS样式中。
    • env()var() 类似,但用来获取环境变量的值。
    • calc() 也可用于创建复杂动画的关键帧(@keyframes)。
    • escape()unescape()(CSS Text Module Level 4草案):对字符串进行URL编码和解码。

随着CSS新特性的不断推出,未来可能会有更多的函数加入进来,以上列举的是目前较常用的一些CSS函数。

84、JS操作DOM的方法有哪些

JavaScript 操作 Document Object Model (DOM) 的方法非常丰富,涵盖了从查找、创建、修改到删除节点的各种操作。以下是主要的操作类别及其相关方法:

  1. 获取节点
    • document.getElementById(id):通过ID获取唯一元素。
    • document.getElementsByName(name):获取具有相同name属性的一组元素集合。
    • document.getElementsByTagName(tagName):获取指定标签名的所有元素集合。
    • document.getElementsByClassName(className):获取具有指定类名的所有元素集合。
    • document.querySelector(selector):根据CSS选择器获取第一个匹配的元素。
    • document.querySelectorAll(selector):根据CSS选择器获取所有匹配的元素集合。
  2. CSS 选择器: 这两种方法利用CSS选择器来定位元素:
    • element.querySelector(selector):在指定元素下查找第一个匹配的选择器的元素。
    • element.querySelectorAll(selector):在指定元素下查找所有匹配的选择器的元素集合。
  3. 文档结构导航
    • node.parentNode:获取当前节点的父节点。
    • node.childNodes:获取当前节点的所有子节点(包括文本节点和元素节点)。
    • node.firstChild / node.lastChild:获取当前节点的第一个/最后一个子节点。
    • node.nextElementSibling / node.previousElementSibling:获取当前节点的下一个/上一个同级元素节点。
    • node.firstElementChild / node.lastElementChild:获取当前元素节点的第一个/最后一个子元素节点。
    • node.childElementCount:获取当前元素节点的子元素个数。
  4. 创建节点
    • document.createElement(tagName):创建一个新的元素节点。
    • document.createTextNode(text):创建一个包含文本内容的新文本节点。
    • document.createComment(data):创建一个注释节点。
    • document.createDocumentFragment():创建一个文档片段节点,可以批量添加子节点。
  5. 添加节点
    • parentNode.appendChild(node):在父节点的子节点列表末尾添加新节点。
    • parentNode.insertBefore(newNode, referenceNode):在参考节点之前插入新节点。
  6. 删除节点
    • parentNode.removeChild(node):从父节点中移除指定的子节点。
  7. 修改节点
    • element.setAttribute(name, value):设置元素的属性值。
    • element.removeAttribute(name):移除元素的属性。
    • element.getAttribute(name):获取元素的属性值。
    • element.innerHTML:读取或设置元素内部的HTML内容。
    • element.textContentelement.innerText:读取或设置元素内的纯文本内容(不包括HTML标签)。
    • element.style.property:访问和修改元素的内联样式。
  8. 事件操作
    • element.addEventListener(type, listener[, options]):添加事件监听器。
    • element.removeEventListener(type, listener[, options]):移除事件监听器。
    • element.dispatchEvent(event):手动触发事件。

以上列出的方法可以帮助开发者灵活地操作页面上的DOM元素,并构建动态交互的Web应用程序。随着时间的推移,现代浏览器还引入了更多的API和优化方法,比如MutationObserver观察DOM变化,Shadow DOM进行组件化封装等。

85、Vue中监听一个对象的方法

在 Vue.js 中,要监听一个对象(无论是普通对象还是响应式对象)的变化,你可以使用 watch 选项。以下是如何在 Vue 组件中监听对象变化的几种常见方法:

方法1:浅层监听整个对象

如果你只需要监听对象本身的替换而不是对象内部属性的更改,可以直接监听整个对象:

Javascript

1export default {
2  data() {
3    return {
4      myObject: { a: 1, b: 2, c: 3 }
5    };
6  },
7  watch: {
8    myObject: {
9      handler(newValue, oldValue) {
10        console.log('myObject changed');
11      },
12      // 默认情况下,Vue 不会对对象内部属性的变化进行深度监听
13      // 若要监听对象内部属性的变更,则需设置 deep: true
14      // deep: true
15    }
16  }
17};

方法2:深度监听对象内部属性的变化

若你需要监听对象内部任意属性的更改,需要开启深度监听(deep watch):

Javascript

1export default {
2  data() {
3    return {
4      myObject: { a: 1, b: 2, c: { d: 4 } }
5    };
6  },
7  watch: {
8    myObject: {
9      handler(newValue, oldValue) {
10        console.log('myObject or any of its nested properties changed');
11      },
12      deep: true // 开启深度监听
13    }
14  }
15};

方法3:监听对象特定属性的变化

如果你想单独监听对象内部某个特定属性的变化,可以直接监听那个属性:

Javascript

1export default {
2  data() {
3    return {
4      myObject: { a: 1, b: 2, c: 3 }
5    };
6  },
7  watch: {
8    'myObject.a': {
9      handler(newValue, oldValue) {
10        console.log('myObject.a property changed');
11      },
12      // 即使这里没有明确指明 deep: true,
13      // 如果 myObject.a 是另一个对象,Vue 仍会进行浅层监听。
14      // 若要深度监听 myObject.a 内部的属性变化,此处仍需设置 deep: true
15      deep: true // 若有必要
16    }
17  }
18};

方法4:结合 computed 属性进行监听

有时你可能希望基于对象属性创建一个计算属性,并在该计算属性的依赖发生变化时执行逻辑。虽然这不是直接监听对象的方式,但在实际开发中常用来间接达到监听的效果:

Javascript

1export default {
2  data() {
3    return {
4      originalObject: { a: 1, b: 2, c: 3 }
5    };
6  },
7  computed: {
8    derivedObject: {
9      get() {
10        return this.originalObject;
11      },
12      set(newValue) {
13        // 新值赋值前可以在此处执行逻辑
14        console.log('derivedObject was updated');
15        // 更新原始对象以触发响应式变化
16        this.$set(this.originalObject, ...);
17      }
18    }
19  },
20  watch: {
21    derivedObject: {
22      handler(newValue, oldValue) {
23        // 此处可监听计算属性的变更,但由于 computed 的 set 已经执行了逻辑,
24        // 通常此处无需额外处理
25      },
26      deep: true // 如果需要深度监听
27    }
28  }
29};

请注意,深度监听会带来一定的性能开销,因为Vue需要递归遍历对象的所有属性来检测变化。因此,在实际项目中,应当根据需求权衡是否启用深度监听。同时,对于非响应式对象或新添加的属性,可能需要使用 this.$setVue.set 方法使其变为响应式的,以便Vue能够正确追踪其变化。

86、堆和栈的区别

  1. 分配方式:栈内存由系统自动分配和管理,它的分配和释放速度比较快。而堆内存是由程序员手动分配和释放的,分配和释放速度相对较慢。
  2. 内存大小:栈是有限的,一般情况下比较小,而堆内存则相对较大,可以根据需求动态扩展。
  3. 数据存储:栈内存主要用于存储局部变量、函数调用、参数传递以及执行上下文等,它的存储方式是“先进后出”,也称为LIFO(Last In First Out);而堆内存用于存储动态分配的对象,对象的生命周期可以比栈内存更长。
  4. 访问方式:栈的访问速度较快,因为它使用的是直接指令操作,而堆则需要通过指针来进行操作,访问速度较慢。
  5. 分配效率:栈的分配效率高,因为系统只需要调整栈指针的位置即可,而堆的分配效率相对较低,系统需要遍历整个堆寻找合适的内存块。

总结起来,栈适用于存储局部变量和临时数据,分配效率高、速度快;而堆适用于存储动态分配的对象,大小灵活、生命周期长。了解堆和栈的区别有助于合理地使用内存,并避免出现内存溢出和内存泄漏等问题。

87、单页应用程序SPA的优缺点

单页应用程序(SPA)是一种Web应用程序的设计模式,它在加载时不会重新加载整个页面,而是通过Ajax请求动态地更新页面的内容。以下是SPA的一些优缺点:

优点:

  1. 用户体验优秀:由于SPA在加载时只需要加载一次页面资源,之后的页面切换都是通过异步请求数据来实现,因此可以提供更快的页面加载速度和更流畅的用户体验。
  2. 前后端分离:SPA通常采用前后端分离的架构,前端负责展示界面和用户交互,后端负责数据处理和业务逻辑,这样有利于团队协作和项目的维护。
  3. 减少服务器负载:由于SPA在一次加载后可以在客户端进行页面的切换和更新,减少了对服务器的请求次数,可以降低服务器的负载压力。
  4. 可以实现跨平台开发:由于SPA通常使用HTML、CSS和JavaScript技术,可以通过各种框架和工具实现跨平台开发,例如React Native、Ionic等。

缺点:

  1. SEO不友好:由于SPA在加载时只加载一次页面,之后的页面切换都是通过JavaScript动态更新页面内容,搜索引擎爬虫无法获取到页面的完整内容,对SEO不友好。
  2. 初次加载时间较长:由于SPA需要加载大量的JavaScript代码和数据,在初次加载时可能会花费较长的时间,特别是对于移动设备和网络环境较差的用户。
  3. 对浏览器的兼容性要求高:由于SPA通常使用了较新的Web技术和API,对浏览器的兼容性要求较高,可能会导致在一些老旧的浏览器上无法正常运行。
  4. 安全性考虑:由于SPA通常将大量的业务逻辑和数据处理移至客户端,可能会增加一定的安全风险,例如容易受到XSS(跨站脚本攻击)等攻击。

综上所述,SPA适用于对用户体验要求较高、前后端分离清晰、不依赖于搜索引擎流量的应用场景,但需要注意其在SEO、初次加载时间和浏览器兼容性方面的一些缺点。

88、什么是MVVM

MVVM(Model-View-ViewModel)是一种软件架构模式,用于构建用户界面,特别是在基于GUI的应用程序中。MVVM模式将用户界面分成三个部分:

  1. Model(模型):模型代表应用程序的数据和业务逻辑。在MVVM中,模型通常是一个简单的类或数据结构,负责管理数据的获取、存储和处理。

  2. View(视图):视图是用户界面的结构和外观。它负责展示模型中的数据,并将用户的输入和操作传递给ViewModel处理。在MVVM中,视图通常是由XML、HTML、XAML等标记语言定义的。

  3. ViewModel(视图模型):视图模型是视图和模型之间的连接器。它负责从模型中获取数据并将其转换为视图可以显示的格式,同时也负责接收来自视图的用户输入和操作,并将其传递给模型处理。ViewModel通常包含了应用程序的业务逻辑和状态管理。

MVVM的核心思想是通过将视图和模型之间的耦合度降低,使得它们可以独立地进行开发和测试。ViewModel充当了中介者的角色,将视图与模型解耦,同时也使得视图的重用和测试变得更加容易。

MVVM常用于基于Web的应用程序、桌面应用程序以及移动应用程序等场景,特别是在需要处理复杂交互和数据绑定的情况下,可以提高开发效率和代码的可维护性。常见的MVVM框架包括AngularJS、Vue.js、React.js等。

89、JS强制类型转换为false的有哪些

  1. undefined
  2. null
  3. false(本身就是一个布尔值)
  4. 0(数字0,包括正0和负0)
  5. NaN(非数字值)
  6. 空字符串 ("")

90、可以获取对象原型的方法有哪些

  1. __proto__属性

    var obj = {};
    console.log(obj.__proto__); // 直接访问对象的 __proto__ 属性获取原型对象
    

    注意:虽然大多数现代浏览器支持__proto__,但它并不是ECMAScript标准的一部分,直到ES6才被正式标准化,但仍不推荐在生产环境中直接使用,因为它有可能在某些环境下不可用或行为不一致。

  2. Object.getPrototypeOf()函数

    var obj = {};
    console.log(Object.getPrototypeOf(obj)); // 使用Object.getPrototypeOf方法获取原型对象
    

    这是标准且安全的方式来获取对象的原型。

  3. 构造函数的prototype属性
    如果你拥有对象的构造函数,并且知道它是通过该构造函数实例化的,那么可以通过构造函数来获取原型对象:

    function MyConstructor() {}
    var obj = new MyConstructor();
    console.log(MyConstructor.prototype); // 这将返回MyConstructor函数的原型对象,同时也是obj的原型
    
  4. Reflect.getPrototypeOf()函数
    ES6引入了Reflect API,其中Reflect.getPrototypeOf()Object.getPrototypeOf()的一个更形式化的版本:

    var obj = {};
    console.log(Reflect.getPrototypeOf(obj)); // 返回对象的原型
    

总结来说,推荐使用Object.getPrototypeOf()Reflect.getPrototypeOf()来确保跨环境兼容性和安全性。而在实际开发中,如果你已经知道对象是由哪个构造函数创建的,则可以通过构造函数的prototype属性来查看或修改原型。不过,这并不适用于那些没有明确构造函数的对象。

  • 6
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值