Skip to content

面试题

1. 动态执行JS有哪些方式?

注意:以下方式都受CSP策略限制,不能在严格模式下使用。

js
// 1. eval函数, 局部作用域
eval('console.log(123)');

// 2. new Function构造函数, 全局作用域
const fn = new Function('console.log(456)');
fn();

// 3. setTimeout和setInterval, 全局作用域
setTimeout('console.log(789)', 0);

// 4. 动态创建script标签, 全局作用域
const script = document.createElement('script');
script.textContent = 'console.log(101112)';
document.head.appendChild(script);

2. 以下的输出是什么?

js
var a = { n: 1};  // 1
var b = a; // 2
a.x = a = { n: 2 }; // 3

console.log(a.x); // undefined
console.log(b.x); // { n: 2 }

这里考查的是赋值操作的顺序,第3步中,可以看成是以下两步:

  1. a.x = (a = {n: 2}),这里的a.x取的地址值已固定, 实际就是b.x,不受后面赋值的影响
  2. 当给a赋值后再给a.x赋值,这里a变了,但是a.x实际也是b.x。、

3. var, let, const 区别?

  1. 作用域不同:var 是函数作用域,let 和 const 是块级作用域。
  2. 变量提升不同:var 存在变量提升,let 和 const 不存在变量提升。
  3. 重复声明不同:var 可以重复声明,let 和 const 不可以重复声明。
  4. 赋值不同:var 可以在声明前赋值,let 和 const 必须在声明后赋值。
  5. const 声明的变量必须初始化,且不能被重新赋值,但如果是对象或数组,可以修改其属性或元素。
  6. var在全局作用域下声明的变量会成为全局对象的属性,而let和const声明的变量不会。

4. 前端有哪些场景会导致内存泄漏?

  1. 全局变量不会被GC,始终被window引用着
  2. 未清理的定时器
  3. 未清理的事件监听器
  4. 闭包滥用导致对象被意外引用
  5. DOM被删除了,但JS引用还在

5. 有使用过哪些设计模式?

  1. 单例模式:整个系统中,只存在一个实例,如Vuex和全局事件中心,某些全局缓存对象
  2. 工厂模式:创建对象时,不暴露具体构造过程,让创建逻辑更清晰。如封装请求模块
  3. 策略模式:将一组可能变化的策略封装成独立函数,通过名称动态调用,如表单验证。
  4. 观察者模式(Observer) / 发布订阅(Pub/Sub):一对多通知机制:一个对象变化自动通知所有订阅者。如:Vue2的依赖收集,事件订阅。
  5. 代理模式:DOM中事件代理
  6. 适配器模式:将一个接口转为另一个接口

6. Web Worker 有什么优缺点?

  1. 优点:
    • 可以在后台线程中执行耗时操作,避免阻塞主线程
    • 可以利用多核处理器的并行计算能力
    • 可以与主线程通过消息传递进行通信
  2. 缺点:
    • 每个Web Worker都是一个独立的线程,不能直接访问主线程的DOM和全局变量
    • 通信成本较高,因为需要通过消息传递来进行数据交换
    • 每个Web Worker都有自己的内存空间,不能直接共享数据

注意: 结构化克隆算法:在主线程和Web Worker之间传递数据时,需要进行序列化和反序列化。而结构化克隆算法可以对复杂对象进行深拷贝,避免引用传递导致的问题。但是在File/Blob时会共享底层数据以避免性能问题。

类型JS 实例共享底层数据共享备注
Object / Array深拷贝
Blob / File推荐大文件
ImageBitmap实现相关
ArrayBuffer默认拷贝
ArrayBuffer (transfer)所有权转移
SharedArrayBuffer真共享
MessagePort转移
OffscreenCanvas转移

7. 你对Vue3的响应式系统的理解?

通过Proxy实现响应式,对目标对象进行代理,当访问响应式数据时,收集effect依赖,修改响应式数据时,触发相应的effect更新。相比于Vue2的Object.defineProperty,Proxy可以监听对象属性的添加和删除,以及数组的变化;性能也Vue2的更好,这是因为Proxy是惰性收集依赖,而defineProperty是初始化的时候就开始全部要收集。

8. echarts大数据性能优化

  1. 通过抽样,聚合、large和progressive减少绘制量
  2. 关闭动画,必要时使用echarts-gl走WebGL渲染
  3. 避免频繁setOption,全量diff,使用appendData和局部更新;
  4. 减少tooltip/hover和事件命中范围,如只在必要区域显示