MST

星途 面试题库

面试题:JavaScript 复杂赋值表达式的性能考量

假设有如下 JavaScript 代码:`let arr = []; for (let i = 0; i < 1000; i++) { arr.push({ key: i }); } let newArr = arr.map((obj) => { return { ...obj, newKey: 'newValue' }; });`。从性能测试角度分析这段代码中涉及的赋值操作,包括数组赋值、对象解构赋值等,指出潜在的性能瓶颈,并说明如何优化和测试优化后的性能。
40.9万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

性能分析

  1. 数组赋值
    • let arr = []; 这一步创建一个空数组,性能开销较小。
    • arr.push({ key: i }); 在循环中使用 push 方法向数组添加对象。由于 push 是一种高效的数组末尾添加元素的方法,性能通常较好,但当数组非常大时,可能会有一定的内存分配和动态扩容开销。
  2. 对象解构赋值
    • return { ...obj, newKey: 'newValue' }; 使用对象展开语法(...)进行解构赋值,它会创建一个新对象,并将 obj 的属性复制到新对象中,然后再添加 newKey 属性。这涉及到对象属性的遍历和复制,当对象属性较多时,会有一定的性能开销。

潜在性能瓶颈

  1. 对象解构赋值开销:在 map 回调函数中频繁使用对象展开语法创建新对象,当 arr 数组长度很大时,对象属性复制操作会带来性能问题。
  2. 内存开销map 方法会返回一个新数组,这意味着在内存中会同时存在 arrnewArr,当数组元素很多时,会占用大量内存。

优化方法

  1. 避免对象解构赋值开销:可以使用 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;
    });
    
  2. 减少内存开销:如果允许修改原数组,可以直接在原数组上操作,而不是使用 map 创建新数组。
    let arr = [];
    for (let i = 0; i < 1000; i++) {
        arr.push({ key: i });
    }
    arr.forEach((obj) => {
        obj.newKey = 'newValue';
    });
    let newArr = arr;
    

性能测试

  1. 使用 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');
    
  2. 使用性能测试库,如 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 });
    

通过上述性能测试方法,可以直观地看到优化前后代码的性能差异,从而评估优化效果。