给定一个JavaScript对象,
var obj = { a: { b: '1', c: '2' } }
和字符串
"a.b"
我怎么把字符串转换成点符号呢
var val = obj.a.b
如果字符串只是'a',我可以使用obj[a]。但这个更复杂。我想应该有什么简单的方法,但现在想不起来了。
给定一个JavaScript对象,
var obj = { a: { b: '1', c: '2' } }
和字符串
"a.b"
我怎么把字符串转换成点符号呢
var val = obj.a.b
如果字符串只是'a',我可以使用obj[a]。但这个更复杂。我想应该有什么简单的方法,但现在想不起来了。
当前回答
其他的建议有点晦涩难懂,所以我想我应该贡献一下:
Object.prop = function(obj, prop, val){
var props = prop.split('.')
, final = props.pop(), p
while(p = props.shift()){
if (typeof obj[p] === 'undefined')
return undefined;
obj = obj[p]
}
return val ? (obj[final] = val) : obj[final]
}
var obj = { a: { b: '1', c: '2' } }
// get
console.log(Object.prop(obj, 'a.c')) // -> 2
// set
Object.prop(obj, 'a.c', function(){})
console.log(obj) // -> { a: { b: '1', c: [Function] } }
其他回答
function at(obj, path, val = undefined) { // If path is an Array, if (Array.isArray(path)) { // it returns the mapped array for each result of the path return path.map((path) => at(obj, path, val)); } // Uniting several RegExps into one const rx = new RegExp( [ /(?:^(?:\.\s*)?([_a-zA-Z][_a-zA-Z0-9]*))/, /(?:^\[\s*(\d+)\s*\])/, /(?:^\[\s*'([^']*(?:\\'[^']*)*)'\s*\])/, /(?:^\[\s*"([^"]*(?:\\"[^"]*)*)"\s*\])/, /(?:^\[\s*`([^`]*(?:\\`[^`]*)*)`\s*\])/, ] .map((r) => r.source) .join("|") ); let rm; while (rm = rx.exec(path.trim())) { // Matched resource let [rf, rp] = rm.filter(Boolean); // If no one matches found, if (!rm[1] && !rm[2]) { // it will replace escape-chars rp = rp.replace(/\\(.)/g, "$1"); } // If the new value is set, if ("undefined" != typeof val && path.length == rf.length) { // assign a value to the object property and return it return (obj[rp] = val); } // Going one step deeper obj = obj[rp]; // Removing a step from the path path = path.substr(rf.length).trim(); } if (path) { throw new SyntaxError(); } return obj; } // Test object schema let o = { a: { b: [ [ { c: { d: { '"e"': { f: { g: "xxx" } } } } } ] ] } }; // Print source object console.log(JSON.stringify(o)); // Set value console.log(at(o, '.a["b"][0][0].c[`d`]["\\"e\\""][\'f\']["g"]', "zzz")); // Get value console.log(at(o, '.a["b"][0][0].c[`d`]["\\"e\\""][\'f\']["g"]')); // Print result object console.log(JSON.stringify(o));
我在我的项目中使用了这个代码
const getValue = (obj, arrPath) => (
arrPath.reduce((x, y) => {
if (y in x) return x[y]
return {}
}, obj)
)
用法:
const obj = { id: { user: { local: 104 } } }
const path = [ 'id', 'user', 'local' ]
getValue(obj, path) // return 104
如果你想把一个字符串点符号转换成一个对象,我已经做了一个方便的小助手,它可以用dotPathToObject(" a.b.c.d ")将一个值为e的字符串转换为a.b.c.d。D ", "value")返回:
{
"a": {
"b": {
"c": {
"d": "value"
}
}
}
}
https://gist.github.com/ahallora/9731d73efb15bd3d3db647efa3389c12
使用数组缩减函数将获得/设置基于提供的路径。
我用a.b.c和a.b.2.c {a:{b:[0,1,{c:7}]}}测试了它,它既可以获取键,也可以将对象更改为设置值
function setOrGet(obj, path=[], newValue){ const l = typeof path === 'string' ? path.split('.') : path; return l.reduce((carry,item, idx)=>{ const leaf = carry[item]; // is this last item in path ? cool lets set/get value if( l.length-idx===1) { // mutate object if newValue is set; carry[item] = newValue===undefined ? leaf : newValue; // return value if its a get/object if it was a set return newValue===undefined ? leaf : obj ; } carry[item] = leaf || {}; // mutate if key not an object; return carry[item]; // return object ref: to continue reduction; }, obj) } console.log( setOrGet({a: {b:1}},'a.b') === 1 || 'Test Case: Direct read failed' ) console.log( setOrGet({a: {b:1}},'a.c',22).a.c===22 || 'Test Case: Direct set failed' ) console.log( setOrGet({a: {b:[1,2]}},'a.b.1',22).a.b[1]===22 || 'Test Case: Direct set on array failed' ) console.log( setOrGet({a: {b:{c: {e:1} }}},'a.b.c.e',22).a.b.c. e===22 || 'Test Case: deep get failed' ) // failed !. Thats your homework :) console.log( setOrGet({a: {b:{c: {e:[1,2,3,4,5]} }}},'a.b.c.e.3 ',22) )
我个人的建议。
除非没有别的办法,否则不要用这种东西!
我看到很多例子,人们用它来翻译json;你会看到locale('app。主页。欢迎')这样的函数。这太糟糕了。如果你已经在object/json中有数据;你知道路径。然后直接使用locale().app.首页示例。欢迎通过改变你的函数返回对象,你得到类型安全,自动完成,不容易出现错别字。
你可以使用npm中提供的库,它简化了这个过程。https://www.npmjs.com/package/dot-object
var dot = require('dot-object');
var obj = {
some: {
nested: {
value: 'Hi there!'
}
}
};
var val = dot.pick('some.nested.value', obj);
console.log(val);
// Result: Hi there!