Angular 奇怪:一个对象属性如何改变两个不同对象的属性?

Angular weirdness: how can one object attribute change an attribute on two different objects?

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

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

我然后select其中一个对象变成了一个变量:

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">

然后我再次更改为个人对象 ($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 中的原始对象(仍然符合预期),但它也将 PERSONAL 对象中 "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"
    }
];

这到底是怎么回事?!几个小时以来,我一直在用头撞墙,尝试了一百万次,并向一位同事求助,但我就是找不到为什么会这样?

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

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

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

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