1

I'm trying to figure out what is going on in the below code that deals with copying one object onto another object. In some cases, they act like the same object where changing one changes the other. I have found numerous posts about how javascript objects are duplicated by reference, and so they are really the same object. For instance, from http://www.w3schools.com/js/js_object_definition.asp:

 var person = {firstName:"John", lastName:"Doe", age:50, eyeColor:"blue"} 
 var x = person;  // This will not create a copy of person. 
 x.age = 10; // This will change both x.age and person.age

 The object x is not a copy of person. It is person. Both x and person
 is the same object. Any changes to x will also change person, because
 x and person are the same object.

However, I have also found a case where the objects appear to be separate objects. How can it act like the same object in one case, but different objects in another? I would appreciate any light on the situation:

Example: http://codepen.io/gratiafide/pen/yagQGr?editors=1010#0

HTML:

<div id="app">
  <my-component>
  </my-component>
</div>

JS:

  var MyComponent = Vue.extend({
  template: '<div v-on:click="test()" class="red">1.  Click here to copy the name object to message and change the value of name to see if the value of message gets changed also.  (It does not).</div>  message: {{ message | json}} <br> name: {{ name | json}}<div v-on:click="test2()" class="red">2.  Now click here to see if updating  the name object also changes the message object.  It does!  Why here and not in #1?</div><div v-on:click="test3()" class="red">3.  Click here to see yet another way of updating the name object also changes the message object. Why here and not in #1?</div>',

  data: function () {
    return { 
    message: {},
    name: {}
    }
  },

  ready: function(){
    this.message = {};
  },
  methods: {
    test: function(){
       this.message = {'t1':"m1"};
       this.name = this.message;  
       this.name = {'t2':"m2"};  
    },
    test2: function(){
       this.message = {'t1':"m1"};
       this.name = this.message;  
       for (var key in this.name) {
                this.name[key] = '';
            }  
    },
    test3: function(){
       this.message = {'t1':"m1"};
       this.name = this.message;  
       Vue.set(this.name, 't1', 'm2');
    }
  }
});

Vue.component('my-component', MyComponent);

new Vue({
  el: '#app'
});

CSS:

@import url(https://fonts.googleapis.com/css?family=Open+Sans);

.red{
  color:red;  
}

body {
  font-family: 'Open Sans', sans-serif;
  background: rgba(0,0,0,.5);
  margin: 0;
}

#app {
  width: 500px;
  margin: 0 auto;
  padding: 10px 20px;
  background: rgba(255,255,255,.9);
}
Bryan Miller
  • 3,262
  • 4
  • 27
  • 51
  • In JavaScript, an *assignment* (or a method argument) does *not* create a copy/clone/duplicate of said object. This rule also applies for properties *within* other objects. – user2864740 Sep 23 '16 at 17:57
  • Possible duplicate of [Is JavaScript a pass-by-reference or pass-by-value language?](http://stackoverflow.com/questions/518000/is-javascript-a-pass-by-reference-or-pass-by-value-language) – VLAZ Sep 23 '16 at 17:58
  • 2
    If you do `a = {}; b = a;` and manipulate `b`, you change the _same_ object. If you do `a = {}; b = a; b = {}` now `b` points to a _different_ object, so manipulating one doesn't change the other. That's pretty much everything, really. – VLAZ Sep 23 '16 at 18:00

2 Answers2

2

Basically, you are asking the difference between these three:

this.message = {'t1':"m1"};
this.name = this.message;  

#1:
this.name = {'t2':"m2"};  

#2
for (var key in this.name) {
  this.name[key] = '';
}  

#3
Vue.set(this.name, 't1', 'm2');

In the first case, you will not change this.message because you are assigning a whole new object to this.name. This new object ({'t2':"m2"}) is completely unrelated to this.message.

Maybe what you were trying/thinking of doing was:

this.name.t2 = "m2";

Which does the same of #2 and #3, affecting this.message, because this.name still refers to the same object.

To assign new properties into an existing object, from another object, you can use Object.assign in browsers which support this function:

Object.assign(this.name, {'t2':"m2"});
J. Bruni
  • 20,322
  • 12
  • 75
  • 92
1

There are 2 types of variables, value and reference. All primitives (i.e. string, number and boolean) are stored by values, and everything else are stored by references and can have properties.

var a,b;
a={c:1};
b=a;
console.log (b===a); // true;

b={c:1}; // note that b is now being assigned a new reference.
console.log (b===a); // false;

a=b; // now a is being assigned the reference of b.
console.log (b===a); // true;

a.c=2; //note that it is the property of a (c) got changed, not a itself.
console.log (b===a); // true;

a.a = a; //now a has a property (a) that stores the reference of a.
console.log(a === a.a);
console.log(a.a === a.a.a);
console.log(a.a === a.a.a.a.a.a.a.a.a);
a.a.a.a.a.a.a.a.a.a.a.c = 10;
console.log(a.c)//10;
There are different ways to declare variables, but that isn't the scope of the question.
Hin Fan Chan
  • 1,543
  • 10
  • 11