阿里云前端一面
- 复盘笔试题
- list2tree函数,我们实际用的pid是哈希值,不能用sort去解决,那么你的算法该怎么改 如果不能使用排序算法来处理节点的顺序,我们可以通过其他方法来构建树形结构。以下是一个基于哈希表的算法,用于将扁平的列表数据转换为树形结构:
function list2tree(list) {
let hash = Object.create(null); // 使用空对象创建一个哈希表
// 将列表中的每个节点以其id为键存储到哈希表中
for (let node of list) {
hash[node.id] = {...node, children: []}; // 添加一个children属性,用于存储子节点
}
// 构建树形结构
let tree = [];
for (let node of list) {
if (node.pid !== null && hash[node.pid]) {
hash[node.pid].children.push(hash[node.id]); // 将当前节点添加为父节点的子节点
} else {
tree.push(hash[node.id]); // 如果没有父节点,则当前节点为根节点
}
}
return tree;
}
这个算法的基本思路是:
- 首先,我们创建一个空的哈希表,用于存储每个节点以其id为键的映射关系。
- 然后,遍历列表中的每个节点,将其存储到哈希表中,并为每个节点添加一个空数组children,用于存储其子节点。
- 最后,再次遍历列表中的每个节点,如果当前节点存在父节点(pid不为null),则将其添加为父节点的子节点;否则,将其添加为根节点。
这种方法的时间复杂度为O(n),其中n为列表中节点的数量。由于使用了哈希表,我们可以在O(1)的时间内获取到每个节点,因此整体的时间复杂度是非常高效的。
- 时间复杂度 空间复杂度是多少 对于上面提供的算法,时间复杂度和空间复杂度如下:
时间复杂度:
- 哈希表构建阶段:遍历列表并将节点存储到哈希表中,时间复杂度为O(n),其中n为列表中节点的数量。
- 树形结构构建阶段:再次遍历列表并将每个节点添加为其父节点的子节点,时间复杂度为O(n)。 因此,总的时间复杂度为O(n)。
空间复杂度:
- 哈希表:使用了一个哈希表来存储节点以其id为键的映射关系,哈希表的空间复杂度为O(n),其中n为列表中节点的数量。
- 树形结构:构建的树形结构仅使用了节点的引用,并不会复制节点的内容,因此树形结构的空间复杂度可以忽略不计。 因此,总的空间复杂度为O(n)。
综上所述,该算法的时间复杂度为O(n),空间复杂度为O(n)。
- 你提到说你有学react源码,那么你深入学习了哪个(react16 18 fiber diff )
6. 详细说一下diff源码
Vue.js 中的 Virtual DOM 实现了一种高效的 DOM 更新策略,其中的核心部分是 diff 算法。diff 算法用于比较前后两次 Virtual DOM 树的差异,并且仅对真正发生变化的部分进行更新,以提高性能。
下面是 Vue.js 中 diff 算法的基本实现思路:
-
初始化:
- 当 Vue 组件首次渲染时,会生成当前组件的 Virtual DOM 树。
- 将该 Virtual DOM 树转换为真实的 DOM,并挂载到页面上。
-
更新:
- 当数据发生变化时,Vue 会重新生成 Virtual DOM 树。
- 将新的 Virtual DOM 树与之前的 Virtual DOM 树进行比较,找出差异。
-
差异查找:
- 从根节点开始逐层对比新旧 Virtual DOM 树的节点。
- 如果节点类型不同,则直接替换整个节点。
- 如果节点类型相同,比较节点的属性和子节点。
-
属性比较:
- 对比新旧节点的属性,找出有变化的属性,并更新到真实 DOM 上。
- 如果属性值发生变化,则更新真实 DOM 上的属性值。
-
子节点比较:
- 对比新旧节点的子节点列表。
- 使用 diff 算法找出最小的更新代价,将差异应用到真实 DOM 上。
- 使用一些优化策略,如同级列表比较、利用唯一 key 进行列表比较等,以提高 diff 的效率。
-
更新 DOM:
- 将找到的差异应用到真实 DOM 上,更新页面显示。
总的来说,Vue.js 中的 diff 算法通过高效地比较新旧 Virtual DOM 树,找出差异,并仅更新真正发生变化的部分,从而提高了页面的渲染性能。Vue.js 中的 diff 算法采用了一些优化策略,如同级列表比较、唯一 key 比较等,以进一步提高 diff 的效率。
React 中的 Virtual DOM 和 diff 算法与 Vue.js 类似,都是用于提高页面渲染性能的关键技术之一。下面是 React 中 diff 算法的基本实现思路:
-
初始化:
- 当 React 组件首次渲染时,会生成当前组件的 Virtual DOM 树。
- 将该 Virtual DOM 树转换为真实的 DOM,并挂载到页面上。
-
更新:
- 当数据发生变化时,React 会重新生成 Virtual DOM 树。
- 将新的 Virtual DOM 树与之前的 Virtual DOM 树进行比较,找出差异。
-
差异查找:
- 从根节点开始逐层对比新旧 Virtual DOM 树的节点。
- 如果节点类型不同,则直接替换整个节点。
- 如果节点类型相同,比较节点的属性和子节点。
-
属性比较:
- 对比新旧节点的属性,找出有变化的属性,并更新到真实 DOM 上。
- 如果属性值发生变化,则更新真实 DOM 上的属性值。
-
子节点比较:
- 对比新旧节点的子节点列表。
- 使用 diff 算法找出最小的更新代价,将差异应用到真实 DOM 上。
- 使用一些优化策略,如同级列表比较、利用唯一 key 进行列表比较等,以提高 diff 的效率。
-
更新 DOM:
- 将找到的差异应用到真实 DOM 上,更新页面显示。
React 中的 diff 算法与 Vue.js 中的类似,都是通过高效地比较新旧 Virtual DOM 树,找出差异,并仅更新真正发生变化的部分,以提高页面的渲染性能。在实际应用中,React 也采用了一些优化策略来进一步提高 diff 的效率,例如利用组件的 shouldComponentUpdate 方法进行自定义的更新控制。
8. 那么为什么要用diff
使用 diff 算法主要是为了提高页面渲染性能,其原因如下:
-
减少 DOM 操作: 直接操作真实 DOM 是非常耗费性能的,因为浏览器需要执行布局和重绘等操作。而 diff 算法能够找出真正发生变化的部分,并只更新这些部分,从而减少了不必要的 DOM 操作,提高了性能。
-
减少重绘次数: 当数据发生变化时,如果直接重新渲染整个页面,会导致大量的 DOM 元素重新绘制,造成页面的重绘。而 diff 算法能够找出真正变化的部分,并只对这部分进行更新,从而减少了页面的重绘次数,提高了性能。
-
减少网络传输量: 在前端框架中,通常会将页面的状态保存在 Virtual DOM 中,然后通过 diff 算法找出变化的部分,并生成最终的 DOM 更新。这样做可以减少网络传输量,因为只需要传输变化的部分,而不是整个页面的内容。
-
提高用户体验: 使用 diff 算法能够实现快速的页面更新,用户可以更快地看到页面的变化,从而提高了用户体验。
综上所述,使用 diff 算法能够有效地提高页面的渲染性能,减少 DOM 操作、减少重绘次数、减少网络传输量,并提高用户体验。因此,现代前端框架都采用了 diff 算法来优化页面渲染过程。
- diff是怎么优化的(又扯到memo可以性能优化)
diff 算法主要通过以下几个方面来优化页面渲染:
-
同级比较: diff 算法会首先比较同级节点,即只比较同一层级的节点,而不会跨层级比较。这样做可以降低 diff 的复杂度,提高比较的效率。
-
利用唯一 key: 在进行列表比较时,diff 算法会利用节点的唯一 key 进行标记,从而快速定位到对应的节点。这样可以避免不必要的节点重新渲染,提高了页面的更新效率。
-
组件级别的更新控制: 在 React 中,组件可以通过 shouldComponentUpdate 方法进行自定义的更新控制。这个方法可以让组件决定是否需要重新渲染,从而避免不必要的 DOM 操作。
-
Memoization: Memoization 是一种将函数的返回值缓存起来的技术。在 React 中,可以通过 useMemo 或 useCallback 来缓存计算结果,避免重复计算。这样可以提高组件的性能,特别是在处理大量计算的场景下。
-
虚拟 DOM: 使用虚拟 DOM 可以将页面状态保存在 JavaScript 内存中,然后通过 diff 算法找出变化的部分,并将这部分更新到真实 DOM 上。这样可以避免直接操作真实 DOM,减少了页面重绘的次数,提高了性能。
综上所述,diff 算法通过同级比较、利用唯一 key、组件级别的更新控制、Memoization 等技术来优化页面的渲染过程,减少了不必要的 DOM 操作,提高了页面的更新效率和性能。在实际应用中,可以根据具体场景选择合适的优化策略,从而达到更好的性能表现。
12. css的作用域 less的作用域(扯到css in modules,优化)
-
在 CSS 中,作用域指的是样式规则的生效范围,即规定了哪些元素会应用该样式。传统的 CSS 是全局作用域的,即样式规则会应用到整个页面上的所有相匹配的元素。而 Less 是一种 CSS 预处理器,它引入了一些新的概念,其中包括作用域的概念。下面分别介绍 CSS 和 Less 中的作用域:
-
CSS 作用域:
- CSS 中的样式规则是全局作用域的,即定义的样式规则会影响到整个页面中所有相匹配的元素。
- 例如,如果你在 CSS 中定义了一个类
.button的样式规则,那么所有具有该类的按钮元素都会应用该样式。
-
Less 作用域:
- Less 中引入了作用域的概念,可以通过一些特殊的语法来定义局部作用域的样式规则。
- 使用 Less 中的
&符号可以引用父选择器,从而实现局部作用域的样式定义。 - 例如,你可以使用 Less 的嵌套语法来定义一个类
.container,并在其中定义一个局部作用域的.button类:.container { .button { // 这里的样式规则只会应用到.container元素内部的.button元素上 } } - 在 Less 中,使用了嵌套语法后,生成的 CSS 中会自动地将嵌套的样式规则展开为全局作用域的样式规则。
总的来说,CSS 是全局作用域的,而 Less 中引入了局部作用域的概念,通过嵌套语法和 & 符号来实现。这样可以更好地组织样式代码,并减少样式规则之间的冲突。
-
你的实习是vue,自己用的是react,那么你自己觉得vue和react哪个好(react)
-
选择 Vue.js 还是 React 取决于项目需求、团队经验和个人偏好等因素,每个框架都有其优点和适用场景。虽然您表示偏向于 React,但下面我还是列举一些 Vue.js 的优点,以供参考:
-
简单易学: Vue.js 的 API 设计简单明了,学习曲线较为平缓,适合初学者快速上手。
-
模板语法: Vue.js 使用了直观的模板语法,可以直接在 HTML 中编写模板,易于理解和维护。
-
双向数据绑定: Vue.js 支持双向数据绑定,当数据发生变化时,视图会自动更新,简化了数据和视图的同步工作。
-
组件化开发: Vue.js 鼓励组件化开发,能够将页面拆分成多个独立的组件,便于复用和维护。
-
生态系统: Vue.js 有着丰富的生态系统,包括 Vue Router、Vuex 等官方插件,以及大量的第三方库和组件,可以满足各种需求。
-
性能优化: Vue.js 内置了一些性能优化的机制,如虚拟 DOM 和异步更新等,可以提高页面的渲染性能。
综上所述,虽然您偏向于 React,但在选择框架时仍然需要根据实际情况进行评估和选择。Vue.js 在某些方面可能更适合特定的项目需求或团队背景,因此也值得考虑和尝试。
16. 为啥react好(开始吟唱)
React 作为一种流行的前端框架,在很多方面具有优势,以下是一些常见的认为 React 好的原因:
-
组件化开发: React 提倡组件化开发,将 UI 拆分为独立的组件,每个组件负责自己的逻辑和渲染,提高了代码的可复用性和可维护性。
-
虚拟 DOM: React 使用虚拟 DOM 技术,通过比较前后两次虚拟 DOM 的差异,最小化 DOM 操作,提高了页面的渲染效率。
-
单向数据流: React 使用单向数据流的数据流模型,数据从顶层组件传递到底层组件,使数据流动更加可控,降低了数据流的复杂度。
-
JSX: React 使用 JSX 语法,将 JavaScript 和 HTML 结合在一起,提高了开发效率和代码的可读性,使组件的编写更加直观和灵活。
-
生态系统: React 有着庞大的生态系统,包括 React Router、Redux、Material-UI 等众多优秀的第三方库和组件,可以满足各种需求,提供了丰富的开发工具和资源。
-
灵活性: React 本身只关注视图层,不涉及其他方面的逻辑,使其可以与其他库和框架灵活组合,适用于各种不同的项目和场景。
-
社区支持: React 有着庞大的社区支持,有很多活跃的开发者和贡献者,提供了丰富的文档、教程和社区资源,使学习和使用 React 变得更加容易和愉快。
综上所述,React 以其组件化开发、虚拟 DOM、单向数据流、JSX、生态系统、灵活性和社区支持等优势,成为了众多开发者和企业选择的首选前端框架之一。
- 为什么学习前端
反问
技术面一共几轮 3轮
部门业务 技术栈
通知结果时间
作者:Ditto___
链接:www.nowcoder.com/discuss/529…
来源:牛客网