【问题标题】:Angular weirdness: how can one object attribute change an attribute on two different objects?角度怪异:一个对象属性如何改变两个不同对象的属性?
【发布时间】:2016-02-18 13:11:52
【问题描述】:

我正在使用 Angularjs 构建一个网站,其中有一个对象列表:

$scope.fieldsToShow = [
    {
        "fields": {},
        "type": "LOGGED_IN"
    },
    {
        "fields": {},
        "type": "PERSONAL",
        "user": 2,
        "name": "Rick Astley"
    }
];

然后我选择其中一个对象到一个变量中:

var $scope.currentObject = $scope.fieldsToShow[1];

让用户使用一些复选框来更改它:

<input ng-model="currentObject.fields.a" type="checkbox">

同时改变$scope.currentObject:

{
    "fields": {
        "a": true
    },
    "type": "PERSONAL",
    "user": 2,
    "name": "Rick Astley"
}

$scope.fieldsToShow中的原始对象:

$scope.fieldsToShow = [
    {
        "fields": {},
        "type": "LOGGED_IN"
    },
    {
        "fields": {
            "a": true
        },
        "type": "PERSONAL",
        "user": 2,
        "name": "Rick Astley"
    }
];

然后我将$scope.currentObject 更改为数组中的第一个对象:

$scope.currentObject = $scope.fieldsToShow[0];

然后我再次单击复选框。正如预期的那样,这也将"a": true 添加到$scope.fieldsToShow 列表中第一个对象的字段对象中。到目前为止,一切都很好。

我现在想在fields 对象中添加一个对象。所以我创建了另一个复选框:

<input ng-model="currentObject.fields.anInnerObject.val" type="checkbox">

然后我再次更改为 PERSONAL 对象 ($scope.currentObject = $scope.fieldsToShow[1];) 并单击复选框。正如预期的那样,这改变了$scope.currentObject

{
    "fields": {
        "anInnerObject": {
            "val": true
        }
    },
    "type": "PERSONAL",
    "user": 2,
    "name": "Rick Astley"
}

$scope.fieldsToShow中的原始对象:

$scope.fieldsToShow = [
    {
        "fields": {},
        "type": "LOGGED_IN"
    },
    {
        "fields": {
            "anInnerObject": {
                "val": true
            }
        },
        "type": "PERSONAL",
        "user": 2,
        "name": "Rick Astley"
    }
];

然后我再次更改为 LOGGED_IN 对象 ($scope.currentObject = $scope.fieldsToShow[0];) 并再次单击复选框。这就是它变得棘手的地方。正如预期的那样,它改变了$scope.currentObject

{
    "fields": {
        "anInnerObject": {
            "val": true
        }
    },
    "type": "LOGGED_IN",
}

它还更改了$scope.fieldsToShow 中的原始对象(仍如预期的那样),但它还将个人对象中"anInnerObject" 的值更改为布尔值true

$scope.fieldsToShow = [
    {
        "fields": {
            "anInnerObject": {
                "val": true  // This changed, which I understand
            }
        },
        "type": "LOGGED_IN"
    },
    {
        "fields": {
            "anInnerObject": true  // BUT WHY this value also change? And why did it become true?
        },
        "type": "PERSONAL",
        "user": 2,
        "name": "Rick Astley"
    }
];

这怎么可能发生?!几个小时以来,我一直在用头撞墙,尝试了一百万种方法,并向同事寻求帮助,但我就是不明白为什么会这样?

有人知道这是怎么发生的吗?欢迎所有提示!

【问题讨论】:

  • 您的描述中缺少的是 fieldsToShow 及其内容的创建方式。从你所描述的一切来看,听起来好像两个 anInnerObjects 是同一个实例实例,而不是不同的对象。

标签: javascript angularjs checkbox reference angular-ngmodel


【解决方案1】:

您需要了解$scope.currentObject$scope.fieldsToShow 中的原始 对象都是相同 对象。两者都只是对相同内存位置的引用。这就是 Javasript 中对非原始类型的引用的工作方式。

如果你想拥有真正独立的不同对象,你需要在使用前克隆它:

var $scope.currentObject = angular.copy($scope.fieldsToShow[1]);

【讨论】:

  • 感谢您的建议。我知道它是对同一个对象的引用。我不想要一个真正独立的对象,因为我确实希望它在$scope.fieldsToShow 中的对象中也发生变化。我在问题的最后一个代码中添加了另一条评论,以澄清我遇到的确切问题。问题是它改变了列表中两个对象的值,而不仅仅是其中一个。知道这是怎么发生的吗?
  • “知道这是怎么发生的吗?”。您发布的内容是不可能的。我认为其他东西会干扰您在问题中未显示的内容。你能复制演示中的问题吗?
  • "你能复制演示中的问题吗?" => 我会试试的。它周围有相当多的代码,所以如果不复制整个js页面就不太容易复制,这会让你很难理解。我会更新问题,并在我成功创建问题演示后通知您..
  • 这就是问题所在。您必须编写很多代码,并且肯定会导致这种行为。正如我所说,您所描述的内容与您发布的内容是不可能的。但是处理简化的演示可能会向您揭示问题,所以它很有用。
  • 好的,我找到了答案。毕竟你是对的:“我有太多代码”,该死.. :-) 最后我找到了一段代码(我什至自己写的),如果用户将 PERSONAL 视图的所有值更改为 true将“LOGGED_IN”中的值设置为 true(出于某些奇怪的业务逻辑原因)。原谅我用这种愚蠢来打扰你。无论如何,我感谢您的宝贵时间。像你这样的人让世界变得更美好.. :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-18
  • 2012-12-13
  • 2018-09-11
  • 2021-05-08
  • 2019-08-08
  • 1970-01-01
相关资源
最近更新 更多