删除运算符与分配给 undefined 或 null

delete operator vs. assigning to undefined or null

foo.v = {
  rolo: 'a',
  cholo: 'b',
  yolo: 'c'
};

我有一个很长的 运行 有状态进程,我为某些类型的请求创建了新对象。我的问题是,如果我在内存中有一个像 v 这样的对象。

它在内存重新分配方面是否更高效:

delete foo.v.cholo;

或者有时这样做更好:

foo.v.cholo = undefined

我在 V8 的内部读到,删除运算符会改变对象并防止它们被垃圾收集或类似的事情轻易收集。参见:

https://github.com/google/google-api-nodejs-client/issues/375

我也会考虑使用 Map 而不是对象,我尝试将 delete 运算符与 Map.prototype.delete 进行比较,但是 delete 运算符在这里的性能更高,也许我的测试不是很好:

{
    const obj = {};

    const start = Date.now();

    for(let i =0; i < 1000000; i++){
        obj['foo'] = true;
        delete obj['foo'];
    }

    console.log('done after:', Date.now() - start);

}



{
    const m = new Map();

    const start = Date.now();

    for(let i =0; i < 1000000; i++){
        m.set('foo',true);
        m.delete('foo');
    }

    console.log('done after:', Date.now() - start);

}

这里是 V8 开发人员。 foo.v.cholo = undefined 肯定比 delete foo.v.cholo 更有效,因为它不会改变对象的形状(=数字、属性和属性的内部位置)。垃圾收集不受影响。使用 undefinednull 作为 zap-out 值并不重要。

一般经验法则:尽可能避免delete

这尤其适用于:

  • 您拥有相同的一组属性,这些属性有时存在有时不存在
  • 您在访问相关对象的(任何)属性时关心性能

另一方面,如果您有大量可能的 属性 名称来来去去(并且不太可能再次出现),例如在 "query string" => "response" 缓存中,那么最好使用 Map 而不是普通对象。