我正在为我的应用程序制作全局数据存储(Angular JS应用程序 - 但这是一个关于JS的问题,特别是Angular的问题。)
我已设置service
来设置数据,获取数据等。
看起来像这样:
angular.module('core').factory('dataService', function(callsService) {
let properties = {
globalData: {}
};
properties.insertData = function(data) {
for (let x in data) {
this.globalData[x] = data[x];
}
return;
}
properties.getData = function(data) {
return this.globalData[data];
}
return properties;
});
使用该服务会是这样的:
dataService.insertData({foo: 'bar'});
dataService.getData('foo'); // 'bar'
但是当存在嵌套数据时会出现问题,如下所示:
dataService.insertData({foo: {bar: 'hello world'}});
dataService.getData('foo'); // {bar: 'hello world'}
这显然是对象引用如何工作,但我怎么能传递像:
dataService.getData('foo.bar'); // 'hello world'
或
dataService.getData('[foo][bar]'); // 'hello world'
回到我的properties.getData
方法,是否有办法以递归方式(或其他方式)访问嵌套对象?
properties.getData = function(data) {
return this.globalData[data]; // needs to be able to get nested objects
}
答案 0 :(得分:2)
更新答案:
我认为这个递归的一个班轮将完全符合您的要求:
properties.getData = (args, data) => args.length ? this.getData(args.slice(1), data ? data[args[0]] : this.globalData[args[0]]) : data ? data : this.globalData
使用无限量的属性参数或数组中的数组索引来调用它,如下所示:
dataService.getData(['arrayOfData', 2, 'propOnArrElement', 'subProp', 'desiredValue'])
<强>解释强>
&#34;签名&#34;该函数的类似于
getData(args: Array, data?: any): any
,
表示:
工作原理:
调用该函数时,
args.length ?
)和
this.getData(
),
args.slice(1),
),data ?
)。
data[args[0]] :
)上的属性(或索引),this.globalData[args[0]])
)。: data ? data
)。: this.globalData
)。我希望你能找到这个有用的,或者至少是愉快的阅读。今晚淋浴时,这个解决方案突然出现在我脑海里,我当然很兴奋。 :P
奖励材料
这是一种类似(甚至更好)的方法,使用ES6 rest参数和Array.reduce(这将允许你在不传递数组的情况下调用函数):
properties.getData = (...args) => args.reduce((data, arg) => data[arg], this.globalData)
像这样打电话:
dataService.getData('firstarg', 'secondarg', 'onemorearg', 'desireddata')
原创,不满意答案:
由于您返回数据,您可以直接在函数调用上访问该属性:
const nestedVal = dataService.getData(‘foo’).bar
或者:
const nestedVal = dataService.getData(‘foo’)[‘bar’]
答案 1 :(得分:1)
这似乎是两个问题之一。
回答您的第一个问题(传递dataService.getData('foo.bar');
您可以使用如下字符串访问对象属性:
var property = foo['bar'];
如果您愿意,可以进行递归,例如:
var property = foo['bar']['baz'];
关于您的第二个问题,这可能与this?
重复答案 2 :(得分:0)
如果我可能建议使用箭头功能作为选择器,例如:
dataService.getData(storage => storage.foo.bar);
您服务中的功能将是:
properties.getData = function (dataSelector) {
return dataSelector(this.globalData);
}
这是一个有效的例子:
const data = {
prop1: {
prop2: 1
}
};
function getData(dataSelector) {
return dataSelector(data);
}
const prop2 = getData(data => data.prop1.prop2);
console.log(prop2);
&#13;
否则你必须使用正则表达式来分割字符串,例如:
properties.getData = function(data) {
var props = data.replace(/\]/g,'').split(/\.\[/g);
return props.reduce((obj, prop) => obj[prop], this.globalData);
}
进一步参考this文章可能有用
答案 3 :(得分:0)
使用$parse
服务:
var object = { 'a': [{ 'b': { 'c': 3 } }] };
var accessor= 'a[0].b.c';
var result = $parse(accessor)(object);
console.log("result =>",result);
// result => 3
angular.module("app",[])
.run(function($parse) {
var object = { 'a': [{ 'b': { 'c': 3 } }] };
var accessor= 'a[0].b.c';
var result = $parse(accessor)(object);
console.log("result =>",result);
// result => 3
})
&#13;
<script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="app">
</body>
&#13;
有关详细信息,请参阅AngularJS $parse Service API Reference。