简体   繁体   中英

javascript variable changing value after changes in original variable

I am having trouble maintaining the original value of a variable after making new changes to the original variable.

Code:

(...)
data = Illumination.calculate_N(data)
data = Illumination.calculate_pi(data)
data = Illumination.calculate_kwh(data)
data = Illumination.calculate_ca(data)           

let data_base = data

let ca_base = data.ca
let kwh_base = data.kwh
let pi_base = data.pi

(...)

data = Illumination.calculate_N(data)
data = Illumination.calculate_pi(data)
data = Illumination.calculate_kwh(data)
data = Illumination.calculate_ca(data)            

let data_proposto = data

let ca_proposto = data.ca
let kwh_proposto = data.kwh
let pi_proposto = data.pi

-----------------------------------
EXAMPLE:
static calculate_ai(data){
  data.ai = data.areaTotal*data.au
  return data
} 

It was expected that the original variable (date) would have its values changed, and this happens correctly, however, the variables data_base and data_proposto are not keeping their values

Both variables at the end of the calculation have the same values as the variable date

The variables ca_proposto, ca_base, and the like store their values correctly

Any idea?

The only interactions of the variables data_base and data_proposto were their creations with the data variable and their return of the function

OBS: If I use console.log () to view the value of the data_base variable before redoing the new calculations (Illumination.calculate_N (data)), the value of the variable appears correctly as it should, it is changed shortly after these calculations.

@chatnoir Defined the problem very well, But I do not agree with his JSON serialization solution due to the below probleam:

You will lose any Javascript property that has no equivalent type in JSON, like Function or Infinity. Any property that's assigned to undefined will be ignored by JSON.stringify, causing them to be missed on the cloned object.

My suggestion to perform deep copy is to rely on a library that's well tested, very popular and carefully maintained: Lodash.

Lodash offers the very convenient clone and deepclone functions to perform shallow and deep cloning.

Lodash has this nice feature: you can import single functions separately in your project to reduce a lot the size of the dependency.

Please find the running sample code here: https://glitch.com/edit/#!/flavio-lodash-clone-shallow-deep?path=server.js:1:0

You are using the same variable data inside and outside functions.

ie; data is in the global scope.

static calculate_ai(data){
  data.ai = data.areaTotal*data.au
  return data
}

even though you are expecting the scope of the variable data inside the method calculate_ai to be limited to that method, it is not the case. data is in global scope and therefore, the value changes inside the method for the variable affects outside as well.

An effective solution is to use a different variable inside the method.

Because in both cases you are assigning not the object itself in the current state, but a reference to that object. What you need to do is to clone the object so the state is frozen at that point.

Simple Clone (Shallow Copy)

let data_base = Object.assign({}, data); //you get a clone of data 

let data_proposto = Object.assign({}, data); 

The limitation here is that it only does a shallow copy. See Deep Copy below for further explanation.

JSON Clone

This is a quick-and-dirty way to clone as it converts a JSON object to a string, and then back. ie you are no longer getting a reference, but a new object.

let data_base = JSON.parse(JSON.stringify(data));

let data_postero = JSON.parse(JSON.stringify(data));

But this won't work if your object is not JSON-safe.

Deep Copy

The least elegant method is probably safest. It deep copies the properties over into a new object. The key difference with Object.assign() is that it copies the values of nested properties, whereas Object.assign() copies the reference to nested objects.

So with Object.assign() any subsequent changes in your nested objects will affect all versions of your "clones". This won't happen if your clones only have property values of those nested objects at the time of cloning – these values are not affected by any changes to the nested objects.

const deepCopy = function(src) {
let target = {};
// using for/in on object also returns prototype properties
for (let prop in src) {
    // .hasOwnProperty() filters out these prototype properties.
    if (src.hasOwnProperty(prop)) {
        target[prop] = src[prop]; //iteratively copies over values, not references
    }
}
return target;
}

let data_base = deepCopy(data);

let data_postero = deepCopy(data);

A variable is like an octopus tentacle , and not as a box (as it's commonly described). In this analogy, the variable's name can be thought of as the name of a tentacle.

A variable (tentacle) holds on to a value in what's called a binding. A binding is an association of a variable to a value: x = 1 .

In JavaScript, if a variable b holds on to variable a , changing the value to which variable a holds onto, will change the value to which variable b holds onto, as b and a are referencing to the same value:

let a = {key: 1}
let b = a
console.log(`a: ${a.key}`) // -> 1
console.log(`b: ${b.key}`) // -> 1

a.key = 2
console.log(`a: ${a.key}`) // -> 2
console.log(`b: ${b.key}`) // -> 2

a = {key: 3} // This will point variable 'a' to a new object, while variable 'b' still points to the original object. 
console.log(`a: ${a.key}`) // -> 3
console.log(`b: ${b.key}`) // -> 2

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