Angular函数通过引用传递作用域变量

3

问题

是否可以通过ng-click调用的函数将作用域变量(特别是数组)按引用传递,并操作该变量的值?

更新: 更明确地说,我的目标是避免在$scope.app.onItemClick中访问$scope。

示例

Javascript:

(function() {
    angular.module('test', [])
    
    angular.module('test').controller('test',['$scope', function ($scope) {
      $scope.app = {};
      
      $scope.app.primarySet = [
        'test1',
        'test2',
        'test3'
      ]
      
      $scope.app.workingSet = [
        'test4',
        'test5',
        'test6'
      ]
      
      /*
       * Attempts to assign $scope.app.primarySet to $scope.app.workingSet using references to those two values.
       */
      $scope.app.onItemClick = function (primarySet, workingSet) {
        primarySet = workingSet
      }
    }])
  })()

相关的HTML:

<button type="button" ng-click="app.onItemClick(app.primarySet, app.workingSet)">Update Primary Set</button>

请查看这个Plunker,以了解此代码的更多上下文。
我对这段代码的期望是,在按下按钮时,$scope.app.primarySet会被设置为$scope.app.workingSet。不幸的是,情况并非如此。在调试中,函数作用域中,primarySet被赋值给workingSet,但是$scope.app.primarySet没有得到修改。
动机
我的动机源于这个SO回答。我认为,如果不直接引用它,测试操作范围的方法会更容易。我也觉得这比让一个函数直接操作范围更简单。
之前的研究
我找到的唯一相关资源是这个SO问题。虽然这个问题很接近,但问题所涉及的参数是字符串,如果我理解正确,就无法像预期的引用那样进行修改。

你试过了吗: <button type="button" ng-click="app.primarySet = app.workingSet">更新主要集合</button> - Pablo Ortuño
@oxigenao,是的,那确实可以工作,但我认为这不是一个好的长期解决方案,因为该映射不应该在模板中,并且无法进行测试。 - jmdarling
oxigenao的建议是正确的,当处理原始类型作为继承时,最好使用'.'。你正在使用的原型继承是JavaScript而不是Angular的结果。https://github.com/angular/angular.js/wiki/Understanding-Scopes提供了一些关于作用域的好信息以及如何浏览它们。 - rlcrews
дёҚдҪҝз”Ё$scope.appзҡ„зӣ®ж Үд»Қ然没жңүи§ЈйҮҠдҪ жғіиҰҒеңЁиҝҷдёӘеҮҪж•°дёӯеҒҡд»Җд№ҲгҖӮдёәд»Җд№ҲдҪ дёҖејҖе§Ӣе°ұдёҚжғідҝ®ж”№дҪңз”ЁеҹҹиҝӣиЎҢжөӢиҜ•е‘ўпјҹ - charlietfl
@charlietfl,这个函数是我能想到的最好的抽象,用于一个更大的应用程序中的一个更大的问题。我不想直接修改作用域进行测试的动机是为了能够仅测试该函数而没有任何副作用,并且无需模拟作用域。在我所代表的更大项目中,我有很多对作用域的引用,这变得非常混乱。虽然这可能是我代码结构不良的迹象,但我正在尝试找到一种强制执行它的模式。希望这有助于澄清一些事情。 - jmdarling
2个回答

1
JavaScript允许您将对象的属性作为键来访问,因此您需要修改模板如下:
<button type="button" ng-click="app.onItemClick(app, 'primarySet', app, 'workingSet')">Update Primary Set</button>

并修改onItemClick方法为:

  $scope.app.onItemClick = function ( leftObject, leftProperty, rightObject, rightProperty) {
    leftObject[leftProperty] = rightObject[rightProperty];
  }

虽然这个方法可行,但在维护和理解发生的事情方面确实是一场噩梦 :) - Mikko Viitala
在大多数情况下,我完全同意!这增加了很多灵活性,而这在玩具示例中并不需要。然而,我期望OP有一套好的支持理由来要求这种灵活性,并将不必要的复杂性因素化简。 - Mark

1
如果您通过onItemClick传递$scope.app,就可以在$scope中更改primarySet,例如:
  (function() {
    angular.module('test', [])

    angular.module('test').controller('test',['$scope', function ($scope) {
      $scope.app = {};

      $scope.app.primarySet = [
        'test1',
        'test2',
        'test3'
      ]

      $scope.app.workingSet = [
        'test4',
        'test5',
        'test6'
      ]

      /*
       * Attempts to assign $scope.app.primarySet to $scope.app.workingSet using references to those two values.
       */
      $scope.app.onItemClick = function (app, workingSet) {
        app.primarySet = workingSet;
      }
    }])
  })()

<button type="button" ng-click="app.onItemClick(app, app.workingSet)">Update Primary Set</button>

当您只传递数组的值到函数时,原因是这样的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接