NodeJS javascript变量在原始变量更改后更改值

s5a0g9ez  于 2023-01-01  发布在  Node.js
关注(0)|答案(4)|浏览(146)

我在对原始变量进行新更改后,无法维护变量的原始值。
代码:

(...)
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
}

预计原始变量(日期)的值 已更改,并且正确发生,但是变量data_base和data_proposto没有保留其值
计算结束时两个变量具有相同的值 作为可变日期,
变量ca_proposto、ca_base等存储它们的值 正确地
你知道吗?
变量data_base和data_proposto的唯一交互是它们与data变量的创建和函数的返回
OBS:如果我在重做新计算(Illumination. calculate_N(data))之前使用console.log()查看data_base变量的值,变量的值会正确显示,但在这些计算之后不久就会更改。

py49o6xq

py49o6xq1#

因为在这两种情况下,你不是在给对象本身赋值,而是给对象赋值一个引用,你需要做的是克隆对象,这样状态就冻结在那个点上了。

简单克隆(浅拷贝)

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

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

此处的限制是它只执行浅拷贝。有关详细说明,请参见下面的深拷贝

JSON克隆

这是一种快速而肮脏的克隆方式,因为它将JSON对象转换为字符串,然后再转换回来。也就是说,您不再获得引用,而是获得一个新对象。

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

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

但如果对象不是JSON安全的,这就行不通了。

深层拷贝

最不优雅的方法可能是最安全的。它将属性深度复制到一个新对象中。与Object.assign()的关键区别在于它复制嵌套属性的 * 值 *,而Object.assign()复制嵌套对象的 * 引用 *。
所以使用Object.assign(),嵌套对象的任何后续更改都会影响所有版本的“克隆体”。如果克隆体在克隆时只有这些嵌套对象的属性值,则不会发生这种情况-这些值不会受到嵌套对象的任何更改的影响。

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);
ecfdbz9o

ecfdbz9o2#

@chatnoir很好地定义了这个问题,但我不同意他的JSON序列化解决方案,因为下面的问题:
您将丢失任何在JSON中没有等价类型的Javascript属性,如Function或Infinity。任何赋值为undefined的属性将被JSON.stringify忽略,导致克隆对象中丢失这些属性。
我建议执行深度复制的方法是依赖一个经过良好测试、非常流行并且精心维护的库:洛达什
Lodash提供了非常方便的克隆和深度克隆功能来执行浅克隆和深克隆。
Lodash有这个很好的功能:你可以在你的项目中单独导入单个函数来减少依赖的大小。
请在此处查找运行示例代码:https://glitch.com/edit/#!/flavio-lodash-clone-shallow-deep?path=server.js:1:0

r9f1avp5

r9f1avp53#

在函数内部和外部使用相同的变量data
data在全局范围内。

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

即使您希望方法calculate_ai内的变量data的作用域限于该方法,但事实并非如此。data在全局作用域中,因此,变量的值在方法内的更改也会影响外部。
一个有效的解决方案是在方法中使用不同的变量。

tyu7yeag

tyu7yeag4#

变量就像章鱼的触手,而不是像通常描述的那样是一个盒子,在这个类比中,变量的名字可以被认为是触手的名字。
一个变量(tentacle)在所谓的绑定中持有一个值,绑定是一个变量与一个值的关联:x = 1.
在JavaScript中,如果变量b保持变量a,则改变变量a保持的值将改变变量b保持的值,因为ba引用相同的值:

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

相关问题