简体   繁体   中英

Javascript - How change object properties without reassign them

The snippet below exposes the doubt

var foo = 'something'
var baz = 'other thing'

var obj = {
  prop1 : 'my prop',
  prop2 : foo,        //referencing external variable
  prop3 : baz         //referencing external variable
}

// here we get the expected obj to be printed
console.log(obj)

// now I change one of the initial variable
foo = 'changed'

// here we get the sabe print as the first, that is the ~problem~   
console.log(obj)

So, how to print 'changed' on prop2 without reassign obj.prop2 = foo

When you do

var obj = {
  prop1 : 'my prop',
  prop2 : foo,        //referencing external variable
  prop3 : baz         //referencing external variable
}

there is no ongoing link between prop2 and the variable foo (or prop3 and baz ). All that happens is that the current value of foo is read, and stored in prop2 (and the same for baz and prop3 ).

If you need prop2 and prop3 to remain linked to foo and baz , you could make them properties with getters . These are properties that trigger a function call when they're read (there are also setters which trigger a function call when the property is set):

var obj = {
  prop1 : 'my prop',
  get prop2() { return foo; },
  get prop3() { return baz; }
};

Accessing obj.prop2 is a hidden function call. Since the function closes over foo , it returns foo 's current value.

Live Example:

 var foo = 'something'; var baz = 'other thing'; var obj = { prop1 : 'my prop', get prop2() { return foo; }, get prop3() { return baz; } }; console.log(obj); foo = 'changed'; console.log(obj); 

Since JavaScript is pass by value instead of pass by reference you cannot override the previous value by assigning it directly to the variable.

You can though make an object of it, and change a property of the object like this:

 var foo = {value: 'something'} var baz = 'other thing' var obj = { prop1 : 'my prop', prop2 : foo, //referencing external variable prop3 : baz //referencing external variable } console.log(obj) foo.value = 'changed' console.log(obj) 

Here's what's happening:

  1. The string "changed" is assigned to the variable foo
  2. The value of foo is assigned to obj.prop2
  3. Because this value is a string (as opposed to an array, object), obj.prop2 simply gets the value. It does not get a reference to foo because these types of values (string, integer, boolean) can be stored in obj as is.

Now let's try the same thing with a different type:

var bloop = [1, 2, 3];
obj.prop4 = bloop;
console.log(obj.prop4); // [1, 2, 3]
bloop.push(4);
console.log(bloop); // [1, 2, 3, 4]
console.log(obj.prop4); // [1, 2, 3, 4]

In this case, what we assign to obj.prop4 is not a value like a string, integer, or boolean. Instead we are assigning a reference to an array stored in a different place in memory. bloop and obj.prop4 both hold a reference to the same array in memory, so if the array is updated, both will update.

This actually works both ways:

obj.prop4.push(5);
console.log(obj.prop4); // [1, 2, 3, 4, 5]
console.log(bloop); // [1, 2, 3, 4, 5]

So in summary if you are dealing with values like strings, ints, booleans you will not be able to change an object's properties the way you are describing. It will work only when the object property is a reference to an array, object, etc.

You're only getting the values of the variables, not linking the variables themselves:

 var foo = 'something' var baz = 'other thing' var obj = { prop1 : 'my prop', prop2 : foo, //getting the value of external variable prop3 : baz //getting the value of external variable } console.log(obj) // change the value of prop2 obj.prop2 = 'changed' console.log(obj) 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM