Question

I tried like this and it works for an object with one property:

var foo = { foo: { foo: { foo: function(){ return x }}}};

function flattenObj(obj) {
  var res;
  for (var k in obj) {
    res = obj[k];
    while (k in res) {
      res = res[k];
    }
  }
  return res;
}

console.log(flattenObj(foo)); // function(){ return x }

How can I make it work with this object?

{ baz: 'baz', foo: { baz: 'baz', foo: function(){ return x }}};

So it returns:

{ baz: 'baz', foo: function(){ return x }}

Edit:

  var obj = {
    a: 1,
    b: 2,
    obj: {
      a: 1,
      b: 2,
      obj: {
        a: 1,
        b: 2,
        obj: function(){ return x }
      }
    }
  }
Was it helpful?

Solution

The demo.

function flattenObj(obj) {
  var tmp, k, res = {};
  for (k in obj) {
    tmp = obj[k];
    while (typeof tmp == 'object' && k in tmp) {
      tmp = tmp[k];
    }
    res[k] = tmp;
  }
  return res;
}

OTHER TIPS

Assuming you know the property name, you could get the last occurence which is not a function :

while (typeof obj.obj !== 'function') {
    obj = obj.obj;
}

Just doing a simple recursive function seems to do the job :

http://jsbin.com/AhAlEHOf/1/edit?js,console

function addOwnProperties (source, target) {
    var properties = Object.keys(source);
  for ( var p in properties ) {
      var key = properties[p];
      var thisObject = source[key];
    if (typeof thisObject != 'object' || Object.keys(thisObject).length == 0) {
        target[key] = thisObject;     
    } else {
      addOwnProperties(thisObject, target) ;
    }
  }
}

test :

var tst ={ baz: 'baz', foo: { baz: 'baz', foo: function(){ return x }}};

var res = {};

addOwnProperties(tst, res) ;

console.log(res);
// output :
// [object Object] {
//  baz: "baz",
//  foo: function (){ return x }
// }

var tst2 = {
    a: 1,
    b: 2,
    obj: {
      a: 3,
      b: 4,
      obj: {
        a: 5,
        b: 6,
        obj: function(){ return x }
      }
    }
  }

var res2 = {};

addOwnProperties(tst2, res2) ;

console.log(res2);
// output :
// [object Object] {
//  a: 5,
//  b: 6,
//  obj: function (){ return x }
//}

Thought I'd share my take on this issue.

Recursive, allows prefixing of parent keys.

var tst2 = {
    a: 1,
    b: 2,
    obj: {
      a: 3,
      b: 4,
      obj: {
        a: 5,
        b: 6,
        obj: function(){ return x }
      }
    }
  };

Object.prototype.flatten = function (separator, prefix) {
    var obj, prefix;
    if (typeof this != 'undefined') {
        separator = separator || '-';
        prefix = arguments.length > 1 ? ((arguments[1].length > 0) ? (arguments[1] + separator) : '') : '';
        obj = arguments.length > 2 ? arguments[2] : {};
        for (var prop in this) {
            if (this.hasOwnProperty(prop)) {
                var path = prefix + prop;
                if (typeof this[prop] == 'object') {
                    if (Object.prototype.toString.call(this[prop]) == '[object Object]') {
                        var flattened = this[prop].flatten(separator, path, obj);
                        for (var flat in flattened) {
                            if (flattened.hasOwnProperty(flat)) {
                                obj[flat] = flattened[flat];
                            }
                        }
                    } else if (typeof this[prop] != 'undefined') {
                        obj[path] = this[prop];
                    }
                } else if (typeof this[prop] != 'undefined') {
                    obj[path] = this[prop];
                }
            }
        }
    }
    return obj || {};
};

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top