1

I created this method based on This question, I modified it to be recursive. It seems to work, but the issue I am having is that I am getting an error that says:

Uncaught TypeError: this.config.routes.forEach is not a function

var obj = {
    config: {
        maxLoadLoop: 5,
        author: {color: "red"}
    },
    run: function(settings){
        this.config = this.mergeOptions(this.config, settings);
        this.config.routes.forEach(function(){/* do some stuff */});
    },
    mergeOptions: function(obj1, obj2){
        var obj3 = {};
        for(var attrname in obj1){
            obj3[attrname] = obj1[attrname];
        }
        for(var attrname in obj2){
            if(Array.isArray(obj2[attrname]) || typeof obj2[attrname] === "object"){
                obj3[attrname] = this.mergeOptions(obj3[attrname], obj2[attrname]);
            }else{
                obj3[attrname] = obj2[attrname];
            }
        }
        return obj3;
    }
};

obj.run(myCustomSettings);

I am merging the following two objects:

{
    maxLoadLoop: 5,
    author: {color: "red"}
}

and this (json converted to object):

{
    "author": {
        "name": "Me",
        "email": "my email"
    },
    "routes": [
        {
            "route": "/home",
            "template": "/templates/home.html",
            "default": true
        },
        {
            "route": "/games",
            "template": "/templates/games.html"
        }
    ]
}

The two seem to merge fine, except that I get the error mentioned above...

Community
  • 1
  • 1
Get Off My Lawn
  • 34,175
  • 38
  • 176
  • 338
  • Setting `obj3 = {}` means you lose any `Array.prototype` methods as it's not an array – Phil Jul 08 '15 at 01:45
  • What is the expected end result? – Sina Khelil Jul 08 '15 at 01:45
  • @Phil what could I do so I maintain that info? – Get Off My Lawn Jul 08 '15 at 01:46
  • Your code does not invoke `.forEach` anywhere. – zerkms Jul 08 '15 at 01:49
  • 1
    Instantiate `obj3` as an object of the same type as `obj1` or `obj2`. That's as specific an answer as you're likely to get unless you tell us what `obj1` and `obj2` are. @zerkms: presumably OP is using a web framework of some kind, which is invoking `this.config.routes.forEach` somewhere; and OP is assigning `this.config.routes` to be a merge of two existing route collections. – Amadan Jul 08 '15 at 01:50
  • @Amadan so according the code in the question - `routes` property holds an array. And there is `.forEach` in an array. – zerkms Jul 08 '15 at 01:51
  • @zerkms: Actually let me rephrase - OP is likely merging `this.config`, as `routes` can be seen to be a property in the posted example. – Amadan Jul 08 '15 at 01:53
  • @The Boogie Man, "routes" when you are converting this json to object, i think it is not converting properly, i mean "routes" is a string here. Check if the "routes" object (converted from json data) is good, by just iterate thru it and print it for testing. – user3278897 Jul 08 '15 at 02:04

1 Answers1

3

I changed line 2:

var obj3 = (!obj1 && Array.isArray(obj2)) ? [] : {};

If we are in the case that obj1 does not exist and obj2 is an array, then the output should also be an array.

If you want to handle the case where both obj1 and obj2 are arrays, you will need to put in a bit more work.

000
  • 26,951
  • 10
  • 71
  • 101
  • Will likely work in this example, as the data seems to be limited to the basic data types without custom prototypes. But it is good to note that it will fail if those are allowed. – Amadan Jul 08 '15 at 01:55