deepFreeze (Object.freeze)

Benchmark created on


Setup

function deepFreeze(obj) {
  const stack = [obj];
  const visited = new WeakSet();
  
  while (stack.length > 0) {
    const current = stack.pop();
    
    if (visited.has(current)) continue;
    visited.add(current);
    
    Object.freeze(current);
    
    for (const key of Reflect.ownKeys(current)) {
      const value = current[key];
      if (
        value !== null &&
        (typeof value === "object" || typeof value === "function") &&
        !Object.isFrozen(value)
      ) {
        stack.push(value);
      }
    }
  }
  
  return obj;
}

function deepFreeze2(object) {
  // Retrieve the property names defined on object
  const propNames = Reflect.ownKeys(object);

  // Freeze properties before freezing self
  for (const name of propNames) {
    const value = object[name];

    if ((value && typeof value === "object") || typeof value === "function") {
      deepFreeze(value);
    }
  }

  return Object.freeze(object);
}

function cowFreeze(obj) {
  return new Proxy(obj, {
    set(target, prop, value) {
      throw new Error("Immutable: cannot modify frozen object");
    },
    get(target, prop) {
      const val = target[prop];
      if (val && typeof val === "object") {
        return cowFreeze(val); // lazily wrap nested objects
      }
      return val;
    }
  });
}

const selfRefObj = { foo: { bar: "baz" } };
selfRefObj.foo.self = selfRefObj;

const config = {
  api: { url: "https://example.com", timeout: 5000 },
  features: { cycle: selfRefObj, darkMode: true }
};

Test runner

Ready to run.

Testing in
TestOps/sec
Stack + WeakSet Cycle Detection
deepFreeze(config);
ready
Recursively Freeze
deepFreeze2(config);
ready
Copy-on-write
cowFreeze(config);
ready

Revisions

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