[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 439
  • Last Modified:

Recursive Object JavaScript Merge Fails...

I'm using the below code to recursively merge some object. All in all it works, but it keeps failing on the two objects below:
o3 should be this:

{onComplete : false, onLoad : false, onWrapUp : {'fbButton' : 'display'}, permissionsNeeded : false};

but instead it keeps coming back with all the values as false.
<script>

function MergeRecursive(obj1, obj2) {

  for (var p in obj2) {
    try {
      // Property in destination object set; update its value.
      if ( obj2[p].constructor==Object ) {
        obj1[p] = MergeRecursive(obj1[p], obj2[p]);

      } else {
        obj1[p] = obj2[p];

      }

    } catch(e) {
      // Property in destination object not set; create it and set its value.
      obj1[p] = obj2[p];

    }
  }

  return obj1;
}



o1 = {onComplete : false, onLoad : false, onWrapUp :false, permissionsNeeded : false};

o2 = {onWrapUp : {'fbButton' : 'display'}};

o3 = MergeRecursive(o1, o2);


console.log(o3);


</script>

Open in new window

0
interclubs
Asked:
interclubs
  • 4
  • 2
1 Solution
 
hieloCommented:
>>// Property in destination object set; update its value.
OK, good, but you need to ACTUALLY test to see if the property exists in the destination object. Try:
function MergeRecursive(obj1, obj2) {

  for (var p in obj2) {
    try {
      // Property in destination object set; update its value.
      if ( obj2[p].constructor==Object && "undefined"!=typeof(obj1[p])) {
        obj1[p] = obj2[p]; 

      } else {
       obj1[p] = MergeRecursive(obj1[p], obj2[p]);

      }

    } catch(e) {
      // Property in destination object not set; create it and set its value.
      obj1[p] = obj2[p];

    }
  }

  return obj1;
}

Open in new window

0
 
interclubsAuthor Commented:
Hmm, that works for that example, but fails later on. The 'facebookButton' object should have all the properties of the first object, but with imgSrc replaced, instead it just has imgSrc
<script>

function MergeRecursive(obj1, obj2) {

  for (var p in obj2) {
    try {
      // Property in destination object set; update its value.
      if ( obj2[p].constructor==Object && "undefined"!=typeof(obj1[p])) {
        obj1[p] = obj2[p]; 

      } else {
       obj1[p] = MergeRecursive(obj1[p], obj2[p]);

      }

    } catch(e) {
      // Property in destination object not set; create it and set its value.
      //alert(obj1[p]);
      obj1[p] = obj2[p];
        //console.log(e);
    }
  }

  return obj1;
}



o1  = {
            'requiredPermissions' : 'offline_access,user_photos,user_videos,friends_videos,friends_photos,user_photo_video_tags',
            'scriptLocation' : '//connect.facebook.net/en_US/all.js',
            'timeOutValue': 4000,
            'debug' : false,
            facebookButton : {
                    onClick : 'fbObject.events.initiateLogin',
                    imgSrc : '///img/facebook_auth_login_button.png',
                    renderImmediately: false,
                    styleProperty: 'display',
                    facebookButtonID : 'facebookButtonID',
                    elementID : 'facebookButton'
                }
                            };


o2 = {welcomeMessage : false, requiredPermissions : 'asdasdsd', facebookButton : {imgSrc : '//zzzz/img/facebook_auth_login_button.png'}};

o3 = MergeRecursive(o1, o2);


console.log(o3);
o1 = {onComplete : false, onLoad : false, onWrapUp :false, permissionsNeeded : false};

o2 = {onWrapUp : {'fbButton' : 'display'}};

o3 = MergeRecursive(o1, o2);


console.log(o3);
</script>

Open in new window

0
 
hieloCommented:
upon closer inspection or your ORIGINAL post, I see you are trying to replace:
onWrapUp :false

with:
onWrapUp : {'fbButton' : 'display'}

What if instead of:
o1={property: false};
o2={property:{'a':'alpha'}}

you had:
o1={property: true};
o2={property:{'a':'alpha'}}

Or even:
o1={property: 23};
o2={property:{'a':'alpha'}}

What then?
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
hieloCommented:
Just to clarify, what I am trying to get at is that with:
o1={property: 23};
o2={property:{'a':'alpha'}}

based on the example you posted, you would be "loosing" that 23. To me that seems is logical. Is that what you really want? If the false in your example is meant as a dummy value, then an empty object would seem more "logical":
o1 = {onComplete : false, onLoad : false, onWrapUp :{}, permissionsNeeded : false};
0
 
interclubsAuthor Commented:
Yeah, my hope was that anything in o2 would update o1, but if something is in 01 that isn't in 02, then it would stay. For the most part it seems to work, except for when you only set one element in o2. facebookButton like in the above example. Instead of just replacing that one value, it overwrite all the other elements in the object.
0
 
hieloCommented:
>>but if something is in 01 that isn't in 02, then it would stay
OK, but I'm not sure if you undertand my question - or at least you have not answered my question. Given:
o1 = {onComplete : false, onLoad : false, onWrapUp :23, permissionsNeeded : false};

o2 = {onWrapUp : {'fbButton' : 'display'}};

o3 = MergeRecursive(o1, o2);

What do you expect for o3?  The issue is that in that particular example you are attempting to merge a non-object
-> 23

with an object:
->{onWrapUp : {'fbButton' : 'display'}}

A property cannot "point" to two items at the same time. If you are using that false as an initial "dummy"/default value, then perhaps this is what you are after:

function MergeRecursive(obj1, obj2) {

	for (var p in obj2) {
		if( "undefined"==typeof(obj1[p])||obj1[p]===false){
			obj1[p]=obj2[p];
		}else if( obj2[p].constructor!==Object ){
			obj1[p] = obj2[p];
		}
		else{
			obj1[p] = MergeRecursive(obj1[p], obj2[p]);
		}
	}
  return obj1;
}

Open in new window

0
 
ProculopsisCommented:

Does jQuery do the job for you - jQuery.extend( o1, o2 );

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head>
<title>http://www.experts-exchange.com/Programming/Languages/Scripting/JavaScript/Q_27035561.html</title>
<script type="text/javascript" src="http://filedb.experts-exchange.com/incoming/2011/05_w20/458595/jquery-1.5.2.min.js"></script>
<script type="text/javascript">

o1 = {onComplete : false, onLoad : false, onWrapUp :false, permissionsNeeded : false};

o2 = {onWrapUp : {'fbButton' : 'display'}};

o3 = jQuery.extend( o1, o2 );

alert( JSON.stringify( o3 ) )

</script>
</head> 
<body />
</html>

Open in new window

0

Featured Post

Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

  • 4
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now