【问题标题】:How can I get/set a value in a nested object when the key 'is.a.string'?当键'is.a.string'时,如何获取/设置嵌套对象中的值?
【发布时间】:2015-04-13 11:57:39
【问题描述】:

我正在一个有角度的应用程序中工作,我正在传递一个对象和一个点表示法的字符串。例如:

$scope.obj = {
    x: 1,
    y: 'a',
    z: {
      eks: 1,
      why: 'a',
      zee: 'orange you glad i didn\'t say banana'
    }
  };
$scope.key = 'z.zee'

我希望能够从对象中获取键的值。由于密钥是一个字符串,我必须构建一个函数

$scope.getValue = function (object, expression) {
    return $parse(expression)(this, object);
};

函数获取值,但现在我需要能够将 obj.z.zee 设置为别的东西,但我做不到

$scope.getValue($scope.obj, "z.zee.punchLine") = 'something else';

$scope.val = $scope.getValue($scope.obj, "z.zee.punchLine");
$scope.val = 'something else';

第一个是错误,第二个只会改变val。

我试图创建一个不依赖于 Angular 解析的函数,但它也没有帮助

function getValue(object, expression) {
    var expresionList = expression.split('.');
    var value = object;
    for(var index = 0; index < expresionList.length; index++) {
        value = value[expresionList[index]];
    }
    return value
}

当对象的点路径为字符串时,有没有办法回写到对象?

这里有一个 Plunker 和 sn-p 可以玩。

angular.module('SimpleApp', [])
  // Attribute Isolated Scope
  .controller('simpleCtrl', function($scope, $parse) {
    $scope.testCtrlScope = 'test controller scope';
    $scope.obj = {
      x: 1,
      y: 'a',
      z: {
        eks: 1,
        why: 'a',
        zee: {
          punchLine: 'orange you glad i didn\'t say banana'
        }
      }
    };
    $scope.getValue = function(object, expression) {
      return $parse(expression)(this, object);
    };
    //alt get value
    //   $scope.getValue = function (object, expression) {
    //     var expresionList = expression.split('.');
    //     var value = object;
    //     for(var index = 0; index < expresionList.length; index++) {
    //         value = value[expresionList[index]];
    //     }
    //     return value;
    // };
    $scope.val = $scope.getValue($scope.obj, "z.zee.punchLine");
    console.log($scope.val, $scope.getValue($scope.obj, "z.zee.punchLine"));
    $scope.val = 'something';
    console.log($scope.val, $scope.getValue($scope.obj, "z.zee.punchLine"));
  });
<div ng-app="SimpleApp">
  <div ng-controller="simpleCtrl">
    {{testCtrlScope}}
  </div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

编辑:doldt 的回答有效。这是我如何使它以角度工作

$scope.setValue = function(object, expression, value) {
    var firstPart = expression.substr(0, expression.lastIndexOf('.'));
    var obj;
    var setterKey;
    if (firstPart) {
      setterKey = expression.substr(expression.lastIndexOf('.') + 1);
      obj = $parse(firstPart)(this, object);
    } else {
      obj = object;
      setterKey = expression;
    }
    obj[setterKey] = value;
  };

【问题讨论】:

    标签: javascript angularjs object key


    【解决方案1】:

    虽然我建议不要这样做 *,但这里有一个解决方案:

    var data = { 
            a:{
              b:{
               c:'hello'
              }
            }
        }
    
    var path = 'a.b.c';
    var parts = path.split('.');
    var result = parts.reduce(function(soFar,element){
         return soFar[element];
    },data);
    

    这会将“hello”放入结果变量中。

    编辑:赋值: 如果这个引用的值是一个对象,您可以分配给您以这种方式提取的引用。否则(对于值类型)更麻烦,​​您必须在最后一次迭代之前停止此循环,并将引用作为倒数第二个对象的 value 属性访问。

    * 为什么我不建议这样做:从长远来看,这种路径表示将成为一场噩梦,它的特殊语义会在您的应用程序中创建紧密耦合,即。使用此代码的每个人都必须了解如何解析此字符串。

    【讨论】:

    • 除了语法之外,这与我在问题底部的替代解决方案不同吗?
    • 乍一看,似乎与此没有什么不同,不。但你的似乎也可以,例如getValue({a:{b:{c:'hello'}}},'a.b.c') 输出“你好”。这个逻辑在什么情况下会产生错误的输出?
    • (如果问题是分配给原始值,请参阅我对我的帖子的粗体编辑:如果您正在处理简单的值类型,则必须提前停止循环以获得参考到价值,而不仅仅是它的价值)
    猜你喜欢
    • 2016-10-31
    • 2021-11-30
    • 1970-01-01
    • 2020-02-24
    • 2021-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多