【问题标题】:How to update object properties on external variable change如何在外部变量更改时更新对象属性
【发布时间】:2020-01-19 09:13:45
【问题描述】:

我又一次偶然发现了我不理解的 Javascript 行为。只要对象外部的变量发生更改,我就需要更新对象的属性。外部变量在对象属性中被引用,所以我认为我所要做的就是从外部更改变量并自动更改属性值。

这是代码的简化版本:

var serverPath = "123/";

var GetCurrentProductionApiConfig = {
  URL: {
    GetStart: serverPath + 'GetCurrentProduction?returnValue=start&',
    GetEnd: serverPath + 'GetCurrentProduction?returnValue=end&',
    Get: serverPath + 'GetCurrentProduction?returnValue=start&'
  }
};

serverPath = "456/";

console.log(GetCurrentProductionApiConfig.URL.GetStart);

这将导致:

123/GetCurrentProduction?returnValue=start&

是因为变量已被复制(通过值传递)而不是指针(通过引用传递)吗?哪种方式是更新属性的正确方式?

【问题讨论】:

  • JS没有引用传递,一切都是值传递。但是,object 的值是它的引用。图元的值是一个直的图元。所以你不能基于原语动态地重新计算东西,例如a = 1; b = 2 + a; a = 4不会改变b。与字符串相同。您可以拥有动态属性,但这是一个花哨的功能。
  • @VLAZ 感谢您提供的信息。传递给函数的 AFAIK 对象变量将是对外部对象的引用,而不是对象的副本,因此至少有类似“按引用传递”的东西。您将如何解决上述问题?用原型函数扩展对象以更新属性?
  • 同样,对象的是它的引用。所以 JS 总是按值传递,即使对于对象也是如此。但是如果你想拥有最新的值,那么你可以让你的属性实际上是方法,所以每次执行它们时,它们都会重新计算返回值。您可以使用getter 隐藏它,这是相同的东西,但它对于使用代码是透明的,obj.dynamicValue 实际上会执行一个函数而不是读取静态属性。
  • @VLAZ 非常感谢您的解释,尤其是链接的 SO 看起来很有希望。如果你能说出你的 cmets 的答案,我会接受这个作为解决方案。

标签: javascript


【解决方案1】:

Everything in JavaScript is pass by value 然而,对象的值恰好是它的引用。然而,这里重要的是,对于原语,当引用的变量发生变化时不会发生变化:

var a = "world";
var obj = {
  b: "hello" + a //evaluated once
}

a = "universe"; //does not modify obj.b which references a

console.log(obj.b); //helloworld

为了有一个动态评估的字符串,你需要调用一个函数或方法:

var a = "world";
var obj = {
  b: function() { 
    return "hello" + a //evaluated every time the function is executed
  }
}
console.log(obj.b()); //helloworld

a = "universe"; //will influence obj.b

console.log(obj.b()); //hellouniverse

但是,这看起来有点“脏”,因为它迫使调用者知道每次都评估属性。如果某些属性是纯字符串,其他功能,它也会引入不一致,如果一个属性必须从一个更改到另一个,这尤其令人讨厌 - 您需要修改调用此代码更改的每个地方,例如,obj.c 到 @ 987654326@.

相反,使用 ES6+,您可以 define a getter 获取与以前相同但会隐藏函数调用的属性,因此,任何时候您读取属性时,您实际上都会评估代码以返回结果:

var a = "world";
var obj = {
  c: "plain property"
}

Object.defineProperty(obj, 'b', {
  get: function() {
    return "hello" + a //evaluated every time the property is read
  }
});

console.log(obj.b); //helloworld

a = "universe"; //will influence obj.b

console.log(obj.b); //hellouniverse
console.log(obj.c); //plain property

【讨论】:

    猜你喜欢
    • 2014-01-19
    • 1970-01-01
    • 2017-09-11
    • 1970-01-01
    • 2023-01-13
    • 1970-01-01
    • 1970-01-01
    • 2012-03-01
    • 1970-01-01
    相关资源
    最近更新 更多