delete vs undefined vs null (v13)

Revision 13 of this benchmark created by Ian Nartowicz on


Description

The delete operator removes a property entirely. Setting a property to null or undefined just changes the value of the key.

Assinging null/undefined is not equivalent to delete since the property can still be enumerated via a for-in loop, Object.keys, Object.getOwnPropertyNames, etc. but in practice they are often used to mean the same thing: that a property is unset.

Using 'delete' is conceptually preferable but the big problem is how the JavaScript engine chooses to react to "delete". JS Engines use "hidden classes" (Shapes) to optimise the code but "delete" supposedly downgrades from a Shape to a hash table which makes every property access significantly slower. To test if this is what actually happens or not, we compare accessing an object's properties after setting to null/undefined vs accessing after deleting to see if the Shape is lost or not (performance for accessing properties got worse).

Tweaked to benchmark only the access afterwards, not the "delete" itself which we already know is slow. Added a case where the properties being deleted were never added.

Preparation HTML

<script>
  'use strict';
  var template = {
    a: 1,
    b: 2,
    c: 3,
    d: 4,
    e: 5,
    f: 6,
    g: 7,
    h: 8,
    i: 9,
    j: '10',
    k: 11,
    l: '12',
    m: function() {
      return 13;
    },
    n: 14,
    o: function() {
      return '15';
    }
  };
  var dump, log = function() {
      dump = arguments;
      };
</script>

Setup

var o1 = {};
    for (var x in template) {
      o1[x] = template[x];
    }
    
    var o2 = {};
    for (var x in template) {
      o2[x] = template[x];
    }
    
    var o3 = {};
    for (var x in template) {
      o3[x] = template[x];
    }
    
    var o4 = {};
    for (var x in template) {
      o4[x] = template[x];
    }
    
    var o5 = {};
    for (var x in template) {
      if (!(x in ["a", "i", "d", "f"])) o5[x] = template[x];
    }
    
    o2.a = null;
    o2.i = null;
    o2.d = null;
    o2.f = null;
    
    o3.a = undefined;
    o3.i = undefined;
    o3.d = undefined;
    o3.f = undefined;
    
    delete o4.a;
    delete o4.i;
    delete o4.d;
    delete o4.f;

Test runner

Ready to run.

Testing in
TestOps/sec
Baseline (no modification)
log(o1.j + o1.l + o1.o(), o1.m());
ready
Setting properties to null
log(o2.j + o2.l + o2.o(), o2.m());
ready
Setting properties to undefined
log(o3.j + o3.l + o3.o(), o3.m());
ready
Deleting properties
log(o4.j + o4.l + o4.o(), o4.m());
ready
Never add properties
log(o5.j + o5.l + o5.o(), o5.m());
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.