帆软前端二面
真的是非常顺畅的一次面试,体验非常棒,面试官的态度和专业知识也非常到位!
1.如何学习前端
2.JS和CSS的一些新特性
3.如何实现一个高精度的定时器
- raf(视觉相关)
- 自校准的setTimeout+performance.now(),
performance.now()
是一个高精度的时间戳,不受系统时间修改的影响,精度远高于Date.now()
- 使用Web Worker
4.使用web worker的话,传递回主线程会被主线程正在进行的任务阻塞吗?
会,优先级类似于微任务
5.absolute的定位是基于谁,fixed的定位是基于什么?
absolut基于最近的已经定位的父级元素,fixed基于视口,window
6.z-index的作用范围?
层级作用域,在同一层级才会生效
7.tcp和udp的区别和使用场景
8.同源策略,跨域和跨站
9.浏览器的并发上限,如何突破这个上限?
- 一般是六个
- HTTP2.0的版本通过多路复用解决了这个问题
- 不是HTTP2.0的版本可以通过域名分片,也就把不同的静态资源分布到多个子域名中,可以进行资源打包和雪碧图类似的想法减少资源请求;或者使用Websocket
10.React和Vue提供的hooks和函数解决了什么问题?
提高逻辑可复用性,从按生命周期/选项来组织逻辑到按逻辑关注点来组织
11.了解哪些React的新特性
12.改代码:React useCallback相关
13.一次遍历找到数组中第k大的元素,如何做?
最小堆或者快速选择比较常见
//最小堆
function findKthLargest(nums, k) {
const minHeap = new MinHeap();
for(const num of nums) {
if (minHeap.size() < k) {
minHeap.push(num);
} else if (num > minHeap.peek()) {
minHeap.pop();
minHeap.push(num);
}
}
return minHeap.peek();
}
// 快速排序,核心思想就是减治
function swap(arr, i, j) {
[arr[i], arr[j]] = [arr[j], arr[i]];
}
function partition(nums, left, right) {
const pivotValue = nums[right];
let storeIndex = left;
for (let i = left; i < right; i++) {
if (nums[i] < pivotValue) {
swap(nums, storeIndex, i);
storeIndex++;
}
}
swap(nums, storeIndex, right);
return storeIndex;
}
function findKthLargest(nums, k) {
const n = nums.length;
const targetIndex = n - k;
let left = 0;
let right = n - 1;
while (left <= right) {
const pivotIndex = partition(nums, left, right);
if (pivotIndex === targetIndex) {
return nums[pivotIndex];
} else if (pivotIndex < targetIndex) {
left = pivotIndex + 1;
} else {
right = pivotIndex - 1;
}
}
}
方法 | 时间复杂度 (平均) | 空间复杂度 | 是否一次遍历 | 是否修改原数组 |
---|---|---|---|---|
最小堆法 | O(n log k) | O(k) | 是 | 否 |
快速选择法 | O(n) | O(log n) 递归栈 | 否 | 是 (in-place) |
排序法 | O(n log n) | O(log n) 排序栈 | 否 | 是 (in-place) |
14.了解哪些排序算法,对于全国人民的身高,用什么排序方法比较好?
- 桶排序
15.手撕:判断二叉树是否为平衡二叉树
16.项目相关