4

I have 2 objects, and combine them by using jQuery.extend function.

john_5_years_ago = {
    name: "john",
    company: "google",
    languages: ["c++", "java"]
}

john_now = {
    name: "john",
    company: "facebook",
    nation: "US",
    languages: ["python", "java", "javascript"]
}

$.extend(true, {}, john_5_years_ago, john_now)

It returns result like this:

{
    name: "john",
    company: "facebook",
    nation: "US",
    languages: ["python", "java", "javascript"]
}

But I expected the value of languages array should be merged, not be overwritten. And the expected result should be like this:

{
    name: "john",
    company: "facebook",
    nation: "US",
    languages: ["python", "java", "javascript", "c++"]
}

I'll appreciate any ideas.

4 Answers 4

1

jQuery.extend() will merge objects and deep will also work. But while merging size of the array wont change and it will not find distinct values. It will substitute those values at the indexes, that is what it does (I have included the describing demo below).

For more details refer the document as well as jQuery code

So this function will not give solution to your case, you should write a custom function (like my solution section).

And to store the deeply merged result in output you should specify it in the second parameter like $.extend(true, john_now, john_5_years_ago);

var john_5_years_ago = {
  name: "john",
  company: "google",
  languages: ["c++", "javascript", "c"],
  extra: {
    aExtra: "aExtra1 value",
    bExtra: "bExtra1 value",
    cExtra: "cExtra1 value"
  }
}

var john_now = {
  name: "john",
  company: "facebook",
  nation: "US",
  languages: ["python", "java", "c", "javascript"],
  extra: {
    aExtra: "aExtra2 value",
    cExtra: "cExtra2 value",
    zExtra: "zExtra2 value"
  }
}

$.extend(true, john_now, john_5_years_ago);
console.log(john_now);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Solution:

Use custom function to loop through those 2 objects for merging two objects deeply.

Note:-

I have also added deep parameter to specify whether the object should be copied in child levels or not.

var john_5_years_ago = {
  name: "john",
  company: "google",
  languages: ["c++", "java"],
  extra: {aExtra:"aExtra1 value", bExtra: "bExtra1 value", cExtra: "cExtra1 value"}
}

var john_now = {
  name: "john",
  company: "facebook",
  nation: "US",
  languages: ["python", "java", "javascript"],
  extra: {aExtra:"aExtra2 value", cExtra: "cExtra2 value", zExtra: "zExtra2 value"}
}

function extend(object1, object2, deep) {
  $.each(object1, function(i, key) {
    if (object1[i] instanceof Array && object2[i] instanceof Array) {
      $.each(object2[i], function(j) {
        if (object1[i].indexOf(object2[i][j]) == -1)
          object1[i].push(object2[i][j])
      });
    }else if(deep === true && object1[i].constructor==={}.constructor && object2[i].constructor==={}.constructor){
    //console.log('{}');
      extend(object1[i], object2[i]);
    } else if(object2[i] != undefined) {
      object1[i] = object2[i];
    }
  });
  $.each(object2, function(j) {
    if (object1[j] === undefined)
      object1[j] = object2[j];
  });
}
extend(john_now, john_5_years_ago, true);
console.log(john_now);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, your explanation gave me a clue. And I found other solution, a bit tricky one. I re-implement function jQuery.extend by adding copy = _.union(src, copy) after line 243. That's it, jQuery.extend works!
1

Try this:

 <!DOCTYPE html>
 <html>
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
 <body>

   <p>Click the button to join two arrays.</p>

    <button onclick="myFunction()">Try it</button>

   <p id="demo"></p>

  <script>
    function myFunction() {

    john_5_years_ago = {
     name: "john",
     company: "google",
     languages: ["c++", "java"]
    }

 john_now = {
   name: "john",
   company: "facebook",
  nation: "US",
  languages: ["python", "java", "javascript"]
 }

 var children  = $.extend(true, {}, john_5_years_ago, john_now);
  console.log(children)
  children = merge_array(children.languages, john_5_years_ago.languages);
  document.getElementById("demo").innerHTML = children;
}

function merge_array(array1, array2) {
  var result_array = [];
  var arr = array1.concat(array2);
  var len = arr.length;
  var assoc = {};
    while(len--) {
      var item = arr[len];
        if(!assoc[item]) 
       { 
         result_array.unshift(item);
         assoc[item] = true;
      }
   }

  return result_array;
 } </script>

</body>
 </html>

Comments

0

You could write this in Plain JS:

var old = {
    name: "john",
    company: "google",
    languages: ["c++", "java"]
}

var now = {
    name: "john",
    company: "facebook",
    nation: "US",
    languages: ["python", "java", "javascript"]
}

Object.keys(old).forEach(function(prop) {
  if(now[prop] != undefined) {
    if(now["languages"] instanceof Array && old[prop] instanceof Array) {
      old[prop].forEach(function(item) {
        if(now[prop].indexOf(item) == -1) {
          now[prop].push(item);
        }
      });
    }
  } else {
    now[prop] = old[prop];
  }
});

console.log(now);

Comments

0

Here you go with a solution https://jsfiddle.net/6c5kgwcw/

var john_5_years_ago = {
    name: "john",
    company: "google",
    languages: ["c++", "java"]
}

var john_now = {
    name: "john",
    company: "facebook",
    nation: "US",
    languages: ["python", "java", "javascript"]
}

$.each(john_now, function(i, key){
  if(i === 'languages'){
    $.each(john_5_years_ago[i], function(j){
      if(john_now[i].indexOf(john_5_years_ago[i][j]) == -1)
    	john_now[i].push(john_5_years_ago[i][j])	
    });
  }
});

console.log(john_now);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

I've used jQuery .each method & loop through the new object.

Hope this will help you.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.