JavaScript optimize a function to check if a nested object is empty

My function needs to check if some nested object is empty.
For flat objects, there is no need of recursion, and a very basic function could be the following (inspired to PHP empty):

empty = function (mixedVar) {
      var undef
      var key
      var i
      var len
      var emptyValues = (undef, null, '');
      for (i = 0, len = emptyValues.length; i < len; i++) {
        if (mixedVar === emptyValues(i)) {
          return true
        }
      }
      if (typeof mixedVar === 'object') {
        for (key in mixedVar) {
          if (mixedVar.hasOwnProperty(key)) {
            return false
          }
        }
        return true
      }

      return false
    }

Now, supposed that the object has several levels of nesting, a recursive version may be needed. It worths nothing that this version adds a “empty” array to pass as input what can be considered as an empty:

  /**
     * Check if an object is empty recursively
     * @param {Object} mixedVar 
     * @param {Array} emptyValues 
     * @param {Number} iter current iteratiom, defaults 0
     * @param {Number} deep recursions levels, defaults 3
     * @returns {Boolean} true if object is empty
     */
    emptyDeep: function(mixedVar, emptyValues = (undefined, null, ''), iter=0, deep=3) {
      var i, len
      for (i = 0, len = emptyValues.length; i < len; i++) {
        if (mixedVar === emptyValues(i)) {
          return true
        }
      }
      if (typeof mixedVar === 'object') {
        for (const item of Object.values(mixedVar)) {
          if(iter>=deep) {
            return false
          } else if (!this.emptyDeep(item, emptyValues, ++iter, deep)) {
            return false
          }
        }
        return true
      }
      return false
    }

This function has also iter and deep variables to control the recursion exit guard at some level of nesting, by defaults 3.
The problem is that with very big objects (order of 10 KB) it turns out that this functions becomes very slow as the object size, and nesting levels grow (like deep > 3).
As results the whole Node IO loop will be affected.
As alternative to this, I have tried this approach, that tries to check the empty for “almost” flatten object, at one level of nesting, and without any recursion:

 /**
     * Check if a flatten object is empty
     * @param {*} obj 
     * @returns 
     */
    emptyFlatten: function(obj) {
      if(this.empty(obj)) return true;
      if(Array.isArray(obj)) {
        return obj.filter(val => this.empty(val)).length==obj.length;
      }
      const keys = Object.keys(obj);
      return keys.map(key => obj(key)).filter(val => this.empty(val)).length==keys.length;
    }

that will work for structures like

()
{},
{ A: {}, B: (), C:null, D:undefined }

but not for a 3 levels object like:

{ A: {}, B: { C: () } }

So, how to optimize the function emptyDeep to make it fast for few levels of recursion (let’s say deep <= 3)?