用Lodash克隆的两个数组是分开的,但相同。为什么?

时间:2018-12-23 05:24:27

标签: javascript arrays angularjs ecmascript-6 lodash

事实上,我知道这里有些事情我很想念,所以非常感谢您的帮助。

我有一个提供两个下拉菜单的功能。它们包含相同的数据(该功能允许两个人之间进行交易,这些人就是数据),但是我希望他们每个人都能获得自己的所说数据副本。

此功能的另一部分是,通过在第一个下拉列表中选择“人物A”,我想在第二个下拉列表中禁用“人物A”,反之亦然,因此我有ng-options标签来关注{{ 1}}属性。

我遇到的问题是,即使在第一次分配时使用Lodash的disabled之类的方法正确地创建“新”数组,每次我访问一个数组中的Person A时(特别是不访问另一个数组)我总是看到当我触摸Person A时,该对象在两个数组中都被更新了,这让我很慌乱。

这感觉像是一个简陋的准系统Javascript问题(标准PEBCAK,我感觉我很误会或直截了当地遗漏了一些基本知识),也许还有一些与AngularJS渲染相关的乐趣参与其中,但是...有什么作用?

clone
angular.module('myApp', [])
  .controller('weirdDataController', function($scope) {
    $scope.$watch('manager1_id', () => {
      if (angular.isDefined($scope.manager1_id) && parseInt($scope.manager1_id, 10) > 0) {
        $scope._disableManagerInOtherDropdown(false, $scope.manager1_id);
      }
    });

    $scope.$watch('manager2_id', () => {
      if (angular.isDefined($scope.manager2_id) && parseInt($scope.manager2_id, 10) > 0) {
        $scope._disableManagerInOtherDropdown(true, $scope.manager2_id);
      }
    });

    $scope._gimmeFakeData = () => {
      return [{
          manager_id: 1,
          manager_name: 'Bill',
          disabled: false
        },
        {
          manager_id: 2,
          manager_name: 'Bob',
          disabled: false
        },
        {
          manager_id: 3,
          manager_name: 'Beano',
          disabled: false
        },
        {
          manager_id: 4,
          manager_name: 'Barf',
          disabled: false
        },
        {
          manager_id: 5,
          manager_name: 'Biff',
          disabled: false
        },
      ];
    };

    const data = $scope._gimmeFakeData();
    $scope.firstManagers = _.clone(data);
    $scope.secondManagers = _.clone(data);

    $scope._disableManagerInOtherDropdown = (otherIsFirstArray, managerId) => {
      const disableManagers = manager => {
        manager.disabled = manager.manager_id === managerId;
      };

      if (otherIsFirstArray) {
        $scope.firstManagers.forEach(disableManagers);
      } else {
        $scope.secondManagers.forEach(disableManagers);
      }

      console.log('Is the first item the same??', $scope.firstManagers[0].disabled === $scope.secondManagers[0].disabled);
    }
  });

我将<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script> <div ng-app="myApp" ng-controller="weirdDataController"> <div class="col-xs-12 col-sm-6"> <select class="form-control" ng-model="manager1_id" ng-options="manager.manager_id as manager.manager_name disable when manager.disabled for manager in firstManagers track by manager.manager_id"> <option value="" disabled="disabled">Choose one manager</option> </select> <select class="form-control" ng-model="manager2_id" ng-options="manager.manager_id as manager.manager_name disable when manager.disabled for manager in secondManagers track by manager.manager_id"> <option value="" disabled="disabled">Choose another manager</option> </select> </div> </div> <br /><br />上的所有相关内容都扔掉了,只是为了使其正常工作并说明问题,但这是怎么回事:

  • 在初始化时,我获取数组,然后为每个下拉列表克隆一个副本
  • 当每个下拉列表更改模型属性(对象ID)时,我都有一个作用域侦听器,然后调用一个方法来处理禁用OPPOSITE列表中的所选对象/人
  • 在此方法中,我确定要迭代的两个列表/数组中的哪个并标记禁用的对象
  • 在此方法的结尾,我做了一个简单的console.log调用,以检查给定对象的值。为了简单起见,我只在索引0处抓取项目。
  • 我期望的是:一个对象的$scope值为disabled,而相反的对象则具有true。我所看到的:他们俩都有false(假设您在下拉菜单中选择了第一个“真实”项目)

怎么了?我到底有多大白痴?

1 个答案:

答案 0 :(得分:0)

我的问题的答案是:@Prop在默认情况下不执行“深度”克隆,因此尽管进行了有缺陷的尝试,但我仍在处理同一阵列。使用Lodash的clone()方法解决了我的问题,但是正如Patrick所建议的那样,我重新评估了如何编写有问题的方法并对其进行重构,从而完全不需要使用任何克隆。