面试题答案
一键面试性能分析
- 数组赋值:
let arr = [];
这一步创建一个空数组,性能开销较小。arr.push({ key: i });
在循环中使用push
方法向数组添加对象。由于push
是一种高效的数组末尾添加元素的方法,性能通常较好,但当数组非常大时,可能会有一定的内存分配和动态扩容开销。
- 对象解构赋值:
return { ...obj, newKey: 'newValue' };
使用对象展开语法(...
)进行解构赋值,它会创建一个新对象,并将obj
的属性复制到新对象中,然后再添加newKey
属性。这涉及到对象属性的遍历和复制,当对象属性较多时,会有一定的性能开销。
潜在性能瓶颈
- 对象解构赋值开销:在
map
回调函数中频繁使用对象展开语法创建新对象,当arr
数组长度很大时,对象属性复制操作会带来性能问题。 - 内存开销:
map
方法会返回一个新数组,这意味着在内存中会同时存在arr
和newArr
,当数组元素很多时,会占用大量内存。
优化方法
- 避免对象解构赋值开销:可以使用
Object.assign
方法替代对象展开语法,因为Object.assign
直接修改目标对象,而不是像对象展开语法那样创建新对象再复制属性。let arr = []; for (let i = 0; i < 1000; i++) { arr.push({ key: i }); } let newArr = arr.map((obj) => { let newObj = Object.assign({}, obj); newObj.newKey = 'newValue'; return newObj; });
- 减少内存开销:如果允许修改原数组,可以直接在原数组上操作,而不是使用
map
创建新数组。let arr = []; for (let i = 0; i < 1000; i++) { arr.push({ key: i }); } arr.forEach((obj) => { obj.newKey = 'newValue'; }); let newArr = arr;
性能测试
- 使用
console.time()
和console.timeEnd()
:// 原代码性能测试 console.time('original'); let arr = []; for (let i = 0; i < 1000; i++) { arr.push({ key: i }); } let newArr = arr.map((obj) => { return { ...obj, newKey: 'newValue' }; }); console.timeEnd('original'); // 优化后代码性能测试(以Object.assign为例) console.time('optimized'); let arr2 = []; for (let i = 0; i < 1000; i++) { arr2.push({ key: i }); } let newArr2 = arr2.map((obj) => { let newObj = Object.assign({}, obj); newObj.newKey = 'newValue'; return newObj; }); console.timeEnd('optimized');
- 使用性能测试库,如
benchmark
:const Benchmark = require('benchmark'); const suite = new Benchmark.Suite; let arr = []; for (let i = 0; i < 1000; i++) { arr.push({ key: i }); } suite .add('original', function () { arr.map((obj) => { return { ...obj, newKey: 'newValue' }; }); }) .add('optimized', function () { arr.map((obj) => { let newObj = Object.assign({}, obj); newObj.newKey = 'newValue'; return newObj; }); }) .on('cycle', function (event) { console.log(String(event.target)); }) .on('complete', function () { console.log('Fastest is'+ this.filter('fastest').map('name')); }) .run({ 'async': true });
通过上述性能测试方法,可以直观地看到优化前后代码的性能差异,从而评估优化效果。