1.前端路由 a ->b -> c这样前进,也可以返回 c-> b->a,用什么数据结构来存比较高效?
前端路由的浏览历史通常使用**栈(Stack)**结构存储,符合后进先出(LIFO)原则。浏览器内置的history对象通过pushState和popState实现前进后退功能。
2.浏览器有哪几种缓存,各种缓存的优先级是什么样的?
- Service Worker Cache:离线缓存,优先级最高。
- Memory Cache:内存缓存,速度快但生命周期短。
- Disk Cache:硬盘缓存,持久化存储。
- Push Cache:HTTP/2推送缓存,会话级存储。
3.Promise 的 finally 怎么实现的?
javascript
Promise.prototype.finally = function(cb) {
return this.then(
value => Promise.resolve(cb()).then(() => value),
reason => Promise.resolve(cb()).then(() => { throw reason })
);
};
4.Promise then 第二个参数和catch的区别是什么?
.then(onFulfilled, onRejected):第二个参数仅处理当前Promise的拒绝状态。.catch(onRejected):会捕获链式调用中前面的所有Promise错误。
5.generator 是怎么做到中断和恢复的?
通过yield关键字暂停执行,保存上下文状态(包括局部变量、指针位置等),调用next()时恢复执行。底层通过协程(Coroutine)实现控制权切换。
6.为什么要区分宏任务和微任务?它们的执行优先级是?
- 宏任务:脚本执行、setTimeout、I/O操作等,每个事件循环处理一个。
- 微任务:Promise回调、MutationObserver等,在每个宏任务结束后立即执行所有微任务。 优先级:微任务 > 宏任务。
7.说说你对 webpack5 模块联邦的了解?
允许不同应用间共享代码,通过ModuleFederationPlugin配置:
javascript
new ModuleFederationPlugin({
name: 'app1',
exposes: { './Button': './src/Button.js' },
remotes: { app2: 'app2@http://localhost:3002/remoteEntry.js' }
});
8.Web Worker 是什么?
浏览器提供的多线程解决方案,通过postMessage通信,不能直接操作DOM。分为专用Worker和共享Worker。
9.说说你对 ToPrimitive 的理解
对象转基本类型时的隐式转换规则:
- 优先调用
valueOf()获取原始值。 - 若未得到基本类型,调用
toString()。 - 可自定义
[Symbol.toPrimitive]方法覆盖默认行为。
10.如果现在设计一个转盘组件,你会考虑哪些方面?有哪些是需要和业务方确认的技
术细节?另外,如何从前端的角度进入消防刷?
- 交互设计:旋转动画、惯性效果、点击区域。
- 业务确认:奖项数据格式、中奖概率算法、接口协议。
- 性能优化:使用CSS硬件加速,避免重绘。
前端消防刷实现
通过监听scroll事件,对比滚动距离与阈值,使用防抖(debounce)优化性能:
javascript
window.addEventListener('scroll', _.debounce(checkFireRisk, 200));
function checkFireRisk() {
if (window.scrollY > dangerThreshold) alert('风险区域!');
}
javascript
console.log(1);
setTimeout(() => console.log(2), 0);
Promise.resolve().then(() => console.log(3));
console.log(4);
输出顺序:1 → 4 → 3 → 2(微任务优先于宏任务)。
11.怎么使用 Math.max、Math.min 获取数组中的最值?
javascript
Math.max(...[1, 2, 3]); // 3
Math.min.apply(null, [1, 2, 3]); // 1
12.怎么实现虚拟列表?
虚拟列表实现
- 计算可视区域显示项数。
- 动态渲染可见项,通过
transform偏移模拟滚动。 - 使用
ResizeObserver和IntersectionObserver优化性能。
12.说说对 requestIdleCallback 的理解
在浏览器空闲期执行低优先级任务,适合非紧急操作(如日志上报)。接收回调函数和超时参数:
javascript
requestIdleCallback(task, { timeout: 2000 });
13.以下等式是成立的吗:1000 000 === 1000000?
数字等式问题
1000 000 === 1000000不成立,因数字字面量中不能包含空格。
14.页面加载的过程中,JS 文件是不是一定会阻塞 DOM和cssom的构建?
JS文件阻塞渲染
- 普通
<script>会阻塞DOM和CSSOM构建。 - 添加
async属性时异步加载,不阻塞解析但执行时仍阻塞。 defer属性保证脚本在DOM解析后顺序执行。
15.var、let、const之间有什么区别?
- var:函数作用域,允许重复声明,存在变量提升。
- let:块级作用域,暂时性死区,不可重复声明。
- const:块级作用域,必须初始化,禁止重新赋值。
16.说说你对轮询的理解
通过定时器周期性检查状态变化:
javascript
const poll = () => {
fetchStatus().then(res => {
if (!res.ready) setTimeout(poll, 1000);
});
};
17.ES6有哪些新特性?
- 箭头函数、模板字符串
- 解构赋值、默认参数
- Class语法、模块化
- Proxy/Reflect、Symbol
18.Reflect是什么?
提供拦截JavaScript操作的统一API,替代部分Object方法:
javascript
Reflect.has(obj, 'key'); // 替代'key' in obj
19.cookie、localStorage和sessionStorage 三者之间有什么区别?
| 特性 | cookie | localStorage | sessionStorage |
|---|---|---|---|
| 生命周期 | 可设置过期时间 | 永久 | 会话结束 |
| 容量 | 4KB | 5MB+ | 5MB+ |
| 自动发送到服务端 | 是 | 否 | 否 |
20.null 和 undefined 有什么区别?
null表示空值,显式赋值。undefined表示未定义,变量声明但未赋值时的默认值。typeof null === 'object'(历史遗留问题)。
21.给某个资源的链接,如 https://www.baidu.com/index.html,请实现一个方法,获取该资源的后缀,如 html
javascript
function getExt(url) {
return url.match(/\.([a-z0-9]+)$/i)?.[1] || '';
}
22.js函数有哪几种声明方式?有什么区别?
函数声明:存在提升
javascript
function foo() {}
函数表达式:无提升
javascript
const foo = function() {};
箭头函数:无this绑定
javascript
const foo = () => {};
23.如何把一个对象变成可迭代对象?
实现[Symbol.iterator]方法:
javascript
const iterable = {
[Symbol.iterator]() {
let step = 0;
return {
next() {
return { value: step++, done: step > 3 };
}
};
}
};
24.说说你对"立即执行函数"的理解
立即执行函数(IIFE)
定义后立即执行的函数,创建独立作用域:
javascript
(function(global) {
// 避免污染全局
})(window);
25.说说你对模块化方案的理解,比如 CommonJS、AMD、CMD、ES Module 分别是什么?
模块化方案对比
- CommonJS :同步加载(Node.js默认),
require/module.exports。 - AMD :异步加载(如RequireJS),
define/require。 - CMD:延迟执行(Sea.js),推崇依赖就近。
- ES Module :静态分析,
import/export,浏览器原生支持。