我有一个这样的数据结构:
var someObject = {
'part1' : {
'name': 'Part 1',
'size': '20',
'qty' : '50'
},
'part2' : {
'name': 'Part 2',
'size': '15',
'qty' : '60'
},
'part3' : [
{
'name': 'Part 3A',
'size': '10',
'qty' : '20'
}, {
'name': 'Part 3B',
'size': '5',
'qty' : '20'
}, {
'name': 'Part 3C',
'size': '7.5',
'qty' : '20'
}
]
};
我想使用这些变量访问数据:
var part1name = "part1.name";
var part2quantity = "part2.qty";
var part3name1 = "part3[0].name";
part1name应该用someObject.part1.name的值填充,即“Part 1”。part2quantity也是一样,它的容量是60。
有没有办法实现这与纯javascript或JQuery?
如果您想要一个能够正确检测和报告路径解析的任何问题的详细信息的解决方案,我为此编写了自己的解决方案——库路径-值。
const {resolveValue} = require('path-value');
resolveValue(someObject, 'part1.name'); //=> Part 1
resolveValue(someObject, 'part2.qty'); //=> 50
resolveValue(someObject, 'part3.0.name'); //=> Part 3A
请注意,对于索引,我们使用.0,而不是[0],因为解析后者会增加性能损失,而.0直接在JavaScript中工作,因此非常快。
然而,完整的ES5 JavaScript语法也被支持,它只需要首先被标记化:
const {resolveValue, tokenizePath} = require('path-value');
const path = tokenizePath('part3[0].name'); //=> ['part3', '0', 'name']
resolveValue(someObject, path); //=> Part 3A
这里的解决方案仅用于访问深度嵌套的键。我需要一个来访问、添加、修改和删除密钥。这是我想到的:
var deepAccessObject = function(object, path_to_key, type_of_function, value){
switch(type_of_function){
//Add key/modify key
case 0:
if(path_to_key.length === 1){
if(value)
object[path_to_key[0]] = value;
return object[path_to_key[0]];
}else{
if(object[path_to_key[0]])
return deepAccessObject(object[path_to_key[0]], path_to_key.slice(1), type_of_function, value);
else
object[path_to_key[0]] = {};
}
break;
//delete key
case 1:
if(path_to_key.length === 1){
delete object[path_to_key[0]];
return true;
}else{
if(object[path_to_key[0]])
return deepAccessObject(object[path_to_key[0]], path_to_key.slice(1), type_of_function, value);
else
return false;
}
break;
default:
console.log("Wrong type of function");
}
};
Path_to_key:数组中的路径。你可以用你的string_path.split(".")替换它。
Type_of_function: 0用于访问(不传递任何值给值),0用于添加和修改。1表示删除。
使用对象扫描,这就变成了一行。然而,更重要的是,这个解决方案考虑性能:
在搜索期间遍历一次输入(即使查询了多个键)
解析只在init上发生一次(如果查询多个对象)
允许使用*进行扩展语法
// const objectScan = require('object-scan');
const someObject = { part1: { name: 'Part 1', size: '20', qty: '50' }, part2: { name: 'Part 2', size: '15', qty: '60' }, part3: [{ name: 'Part 3A', size: '10', qty: '20' }, { name: 'Part 3B', size: '5', qty: '20' }, { name: 'Part 3C', size: '7.5', qty: '20' }] };
const get = (haystack, needle) => objectScan([needle], { rtn: 'value', abort: true })(haystack);
console.log(get(someObject, 'part1.name'));
// => Part 1
console.log(get(someObject, 'part2.qty'));
// => 60
console.log(get(someObject, 'part3[0].name'));
// => Part 3A
const getAll = (haystack, ...needles) => objectScan(needles, { reverse: false, rtn: 'entry', joined: true })(haystack);
console.log(getAll(someObject, 'part1.name', 'part2.qty', 'part3[0].name'));
/* =>
[ [ 'part1.name', 'Part 1' ],
[ 'part2.qty', '60' ],
[ 'part3[0].name', 'Part 3A' ] ]
*/
console.log(getAll(someObject, 'part1.*'));
/* =>
[ [ 'part1.name', 'Part 1' ],
[ 'part1.size', '20' ],
[ 'part1.qty', '50' ] ]
*/
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan@13.8.0"></script>
声明:我是object-scan的作者
也适用于对象内的数组/数组。
防御无效值。
/**
* Retrieve nested item from object/array
* @param {Object|Array} obj
* @param {String} path dot separated
* @param {*} def default value ( if result undefined )
* @returns {*}
*/
function path(obj, path, def){
var i, len;
for(i = 0,path = path.split('.'), len = path.length; i < len; i++){
if(!obj || typeof obj !== 'object') return def;
obj = obj[path[i]];
}
if(obj === undefined) return def;
return obj;
}
//////////////////////////
// TEST //
//////////////////////////
var arr = [true, {'sp ace': true}, true]
var obj = {
'sp ace': true,
arr: arr,
nested: {'dotted.str.ing': true},
arr3: arr
}
shouldThrow(`path(obj, "arr.0")`);
shouldBeDefined(`path(obj, "arr[0]")`);
shouldBeEqualToNumber(`path(obj, "arr.length")`, 3);
shouldBeTrue(`path(obj, "sp ace")`);
shouldBeEqualToString(`path(obj, "none.existed.prop", "fallback")`, "fallback");
shouldBeTrue(`path(obj, "nested['dotted.str.ing'])`);
<script src="https://cdn.rawgit.com/coderek/e7b30bac7634a50ad8fd/raw/174b6634c8f57aa8aac0716c5b7b2a7098e03584/js-test.js"></script>