本文最后更新于849 天前,其中的信息可能已经过时,如有错误请评论留言
Round One
1、简单说一下js中的数据类型
-
答:
基本数据类型
- String: 字符串,用单引号或双引号包裹
- Number: 数字,包括整数和小数,也包括特殊的数值, 如
Infinity,-Infinity和NaN - Boolean: 布尔值,只有
true或false - Null: 空值
- Undefined: 未定义的值
引用数据类型
- Array: 存储有序元素的集合
- Object: 存储键值对的集合
- Date: 表示日期和时间的对象
- RegExp: 表示正则表达式的对象
- Function: 存储代码块的对象
ES6 新增数据类型
- Symbol: 唯一且不可变的值
- BigInt: 超过 Number 范围的大整数
- Map: 存储键值对的集合,键可以是任何数据类型
- Set: 存储唯一值的集合
- WeakMap: 存储键值对的集合,键是弱引用,不会阻止垃圾回收
- WeakSet: 存储唯一值的集合,值是弱引用,不会阻止垃圾回收
2、什么是闭包
-
答:
闭包(Closure)指的是一个函数能够访问并操作它所定义时所在的外部函数作用域中的变量,即使外部函数已经执行完毕返回了。
闭包的特点:
- 函数嵌套: 闭包必定是一个内部函数,它是在一个外部函数中定义的。
- 外部函数的变量访问: 内部函数可以访问并操作外部函数中的变量,即使外部函数已经执行完毕。
- 延长外部函数变量的生命周期: 由于内部函数可以访问外部函数的变量,所以外部函数的变量不会随着外部函数的执行而被销毁,而是会一直存在于内存中,直到内部函数被销毁。
闭包的主要用途包括:
- 数据封装和私有变量: 利用闭包可以创建私有变量和方法,实现数据的封装和隐藏。
- 函数柯里化: 利用闭包可以实现函数的柯里化,从而实现函数的部分求值。
- 事件处理和回调函数: 利用闭包可以在回调函数中访问外部环境的变量。
- 内存管理: 由于闭包会导致原有的作用域链不被释放,因此需要注意避免内存泄漏的问题。
3、简述作用域和作用域链
- 答:
- 作用域(Scope):
- 作用域是程序中变量和函数的可见性和生命周期。
- 作用域分为全局作用域和局部作用域(函数作用域、块级作用域)。
- 变量在声明时就确定了它的作用域,作用域决定了变量的可见性。
- 作用域遵循就近原则,即先在当前作用域中查找变量,如果没有找到则向上级作用域查找。
- 作用域链(Scope Chain):
- 作用域链是一个由所有父级作用域组成的链条。
- 当在一个作用域中访问一个变量时,JavaScript 引擎会沿着作用域链向上级作用域查找,直到找到该变量或者到达全局作用域。
- 作用域链的方向是从内向外,从局部到全局。
- 作用域链决定了标识符的解析顺序,保证了程序的有序性和数据的安全性。
- 作用域(Scope):
4、简述CSS的重排和重绘
-
答:
CSS 重排
- 当 DOM 结构发生变化时触发。
- 浏览器必须重新计算元素的几何属性(位置、大小、边距等)。
- 这是个耗时的过程,会对页面性能产生负面影响。
CSS 重绘
- 当元素的外观发生变化(例如颜色、背景、文本)时触发。
- 浏览器必须重新绘制受影响的像素。
- 比重排快,但仍然会影响性能。
重排和重绘之间的区别
- 触发器:重排由 DOM 结构变化触发,而重绘由元素外观变化触发。
- 影响:重排需要重新计算元素几何属性,而重绘仅重新绘制受影响的像素。
- 性能影响:重排比重绘更耗时,对页面性能影响更大。
优化重排和重绘
- 避免在循环中频繁修改 DOM。
- 使用 CSS 类和转换而不是内联样式。
- 减少元素层级结构。
- 使用 GPU 加速,例如 CSS
translate和transform。 - 使用 CSS
will-change属性通知浏览器即将发生的重排或重绘。
5、for...in和for...of的区别
-
答:
- 遍历对象与遍历数组:
for...in循环用于遍历对象的可枚举属性,包括从原型继承的属性。for...of循环用于遍历可迭代对象(如数组、字符串、NodeList 等),它会遍历对象的元素值。
- 遍历顺序:
for...in循环的遍历顺序是不确定的,因为它会遍历对象的所有可枚举属性,包括从原型继承的属性。for...of循环会按照数据结构的自然顺序进行遍历,对于数组来说就是索引顺序。
- 遍历对象属性:
for...in循环可以遍历对象的所有可枚举属性,包括从原型继承的属性。for...of循环无法直接遍历对象的属性,因为对象不是可迭代的。如果需要遍历对象的属性,可以使用Object.keys(),Object.values()或Object.entries()配合for...of循环使用。
- 遍历性能:
- 一般来说,
for...of循环的性能要优于for...in循环,因为for...in循环需要检查原型链上的属性,而for...of循环只需要遍历可迭代对象的元素。
- 一般来说,
总的来说,
for...in更适合遍历对象属性,而for...of更适合遍历数组或其他可迭代对象。 - 遍历对象与遍历数组:
6、for item in 对象遍历时,item是什么?
-
答:
for...in循环遍历对象时,item变量表示的是对象的键(key),而不是值(value)。
7、v-if和v-show的区别?哪个性能更好?
-
答:
- 渲染方式:
v-if: 当条件为 false 时,元素不会被渲染到 DOM 中。它会根据条件动态地创建或销毁元素。v-show: 当条件为 false 时,元素的display属性会被设置为none。元素仍然存在于 DOM 中,只是被隐藏了。
- 初始渲染性能:
v-if: 只有当条件为 true 时,元素才会被渲染。这意味着初始渲染时,v-if会更快一些。v-show: 元素始终会被渲染到 DOM 中,只是通过 CSS 属性进行隐藏。这意味着初始渲染时,v-show会更慢一些。
- 切换性能:
v-if: 每次条件变化时,都会销毁和创建元素。对于频繁切换的场景,v-if会比v-show慢。v-show: 元素只需要通过修改 CSS 属性来切换可见性,这通常比销毁和创建元素快得多。对于频繁切换的场景,v-show会更快。
- 生命周期:
v-if: 当条件为 false 时,元素及其子组件的生命周期钩子都不会被触发。v-show: 元素及其子组件的生命周期钩子会一直被触发,无论条件是否满足。
总的来说:
- 如果需要在运行时很少改变条件的场景中,使用
v-if会更合适,因为它可以确保条件块内的事件监听器和子组件适当地被销毁和重建。 - 如果需要频繁切换条件的场景中,使用
v-show会更合适,因为它不会销毁和重建元素,性能会更好。
- 渲染方式:
8、简单说一下快速排序的过程
-
答:
- 从数列中挑出一个元素作为基准(pivot)。
- 将所有比基准小的元素放在基准左边,所有比基准大的元素放在基准右边。这个过程称为分区(partition)操作。
- 递归地(recursive)把左右两个小问题排序。
拓展:
function quickSort(arr) { if (arr.length <= 1) { return arr; } const pivotIndex = Math.floor(arr.length / 2); const pivot = arr.splice(pivotIndex, 1)[0]; const left = []; const right = []; for (let i = 0; i < arr.length; i++) { if (arr[i] < pivot) { left.push(arr[i]); } else { right.push(arr[i]); } } return quickSort(left).concat([pivot], quickSort(right)); } // 使用示例 const unsortedArray = [5, 2, 9, 1, 7, 3, 8, 4, 6]; const sortedArray = quickSort(unsortedArray); console.log(sortedArray); // 输出: [1, 2, 3, 4, 5, 6, 7, 8, 9]这个实现遵循了快速排序的基本步骤:
- 如果数组长度小于或等于 1,直接返回该数组。
- 选择数组中间的元素作为基准点(pivot)。
- 将数组分成两部分:小于基准点的元素放在左边数组,大于或等于基准点的元素放在右边数组。
- 递归地对左右两个子数组进行快速排序。
- 最后将左右两个排好序的子数组合并起来,即得到排好序的数组。
时间复杂度为 O(n log n),是一种非常高效的排序算法。



