当键 'is.a.string' 时,如何 get/set 嵌套对象中的值?

How can I get/set a value in a nested object when the key 'is.a.string'?

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

$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 和可以玩的片段。

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 的回答有效。这是我在 angular

中的工作方式
$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;
  };

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

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" 放入结果变量中。

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

* 为什么我反对它:这种路径表示将成为长期使用的噩梦运行,它的特殊语义会在你的应用程序,即。使用此代码的每个人都必须了解如何解析此字符串。