I know this question has been discussed so many times, and I think I got a basic idea. There are some top rated answers I found from StackOverflow:
But all the answers seems very fuzzy to me.
Let's consider the example below:
const user = {
  name: "James",
  age: 33,
  highlights: {
    career: "Basketball player",
    NBAChampion: [2012, 2013, 2016],
  },
  promotion: () => ("Get LeBron15 now!"),
};
const james = user;
const clone = { ...user };
const clone2 = Object.assign({}, user);
const clone3 = JSON.parse(JSON.stringify(user));
const clone4 = {
  ...user,
  highlights: {
    ...user.highlights,
    // I comment the it out, so now NBAChampion is a reference rather than copy!
    // NBAChampion: [...user.highlights.NBAChampion]
  }
};
user.age++;
user.highlights.career = "football player";
console.log('james', james, james === user, james == user);
console.log('clone', clone, clone === user, clone == user);
console.log('clone2', clone2, clone2 === user, clone2 == user);
console.log('clone3', clone3, clone3 === user, clone3 == user);
// console.log(clone3.promotion()); // My problem with clone3 is that function's been removed. 
console.log('clone4', clone4, clone4 === user, clone4 == user);- jamesis a reference, it's always exactly same as user;
- cloneis a copy. Is it a shallow copy or deep copy? The- nameand- ageare separated from- user, but the- highlightsis still a reference.
- clone2behaves exactly the same as- clone.
- clone3is converted from a string. Is it a deep copy? It is not a perfect clone, since functions (if there's any) are not save to convert this way.
- clone4is copied every layer of- user, so I can call it a "deep copy".
 However if the spread operator only creates deep copy sometimes, then how can I test if the new object is a deep copy or not?
Update: I commented NBAChampion out in clone4, so now NBAChampion is a reference rather than copy! If I push a new value in user.highlights.NBAChampion, clone4 will also updates.
What should we call this type of object? It's neither a shallow nor deep copy. 
Why does this matter?
React has a shouldComponentUpdate() function which compares shallow copy. There is the link.
In React source code (Line: 356), the shallow comparison is done like this:
shouldComponentUpdate(nextProps) {
  return this.props.children !== nextProps.children;
}
In the code demo above, the 2nd and 3rd parameters in console.log show the comparison results between clone and user. However, only 1st copy returns true. (Note: there is no different between strict comparison and abstract comparison)
If I apply shouldComponentUpdate to the demo above, obviously only james and user will return true. So james is a shallow copy in Facebook's code. Then my questions are:    
- Are reference and shallow copy exactly the same thing in JS? If not, why React do this?
- How can I test a object is a shallow copy or deep copy in my test case?
The question took me lots of time to craft. Any clear explanation with example is welcome.
Thanks a lot.
 
     
    