给定一个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-path。 https://github.com/mariocasciaro/object-path
可在NPM和BOWER上使用 https://www.npmjs.com/package/object-path
很简单:
objectPath.get(obj, "a.c.1"); //returns "f"
objectPath.set(obj, "a.j.0.f", "m");
并且适用于深度嵌套的属性和数组。
其他回答
如果您希望以尽可能快的方式做到这一点,同时处理与路径解析或属性解析有关的任何问题,请检查path-value。
const {resolveValue} = require('path-value');
const value = resolveValue(obj, 'a.b.c');
该库是100%的TypeScript,适用于NodeJS +所有web浏览器。它是完全可扩展的,你可以使用较低级别的resolvePath,如果你愿意,你可以用自己的方式处理错误。
const {resolvePath} = require('path-value');
const res = resolvePath(obj, 'a.b.c'); //=> low-level parsing result descriptor
你可以通过点表示法获得对象成员的值,只需一行代码:
new Function('_', 'return _.' + path)(obj);
对你来说:
var obj = { a: { b: '1', c: '2' } }
var val = new Function('_', 'return _.a.b')(obj);
为了简化,你可以这样写一个函数:
function objGet(obj, path){
return new Function('_', 'return _.' + path)(obj);
}
解释:
Function构造函数创建一个新的Function对象。在JavaScript中,每个函数实际上都是一个function对象。使用function构造函数显式创建函数的语法如下:
new Function ([arg1[, arg2[, ...argN]],] functionBody)
其中arguments(arg1到argN)必须是一个对应于有效javaScript标识符的字符串,functionBody是一个包含包含函数定义的javaScript语句的字符串。
在我们的例子中,我们利用字符串函数体来检索点表示法的对象成员。
希望能有所帮助。
我从Ricardo Tomasi的回答中复制了以下内容,并进行了修改,以创建还不存在的子对象。它的效率有点低(更多的if和创建空对象),但应该很好。
它还允许我们做Object。Prop (obj, 'a.b', false)我们之前做不到。不幸的是,它仍然不允许我们赋值为undefined…我还不知道该怎么做。
/**
* Object.prop()
*
* Allows dot-notation access to object properties for both getting and setting.
*
* @param {Object} obj The object we're getting from or setting
* @param {string} prop The dot-notated string defining the property location
* @param {mixed} val For setting only; the value to set
*/
Object.prop = function(obj, prop, val){
var props = prop.split('.'),
final = props.pop(),
p;
for (var i = 0; i < props.length; i++) {
p = props[i];
if (typeof obj[p] === 'undefined') {
// If we're setting
if (typeof val !== 'undefined') {
// If we're not at the end of the props, keep adding new empty objects
if (i != props.length)
obj[p] = {};
}
else
return undefined;
}
obj = obj[p]
}
return typeof val !== "undefined" ? (obj[final] = val) : obj[final]
}
使用数组缩减函数将获得/设置基于提供的路径。
我用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.首页示例。欢迎通过改变你的函数返回对象,你得到类型安全,自动完成,不容易出现错别字。
我想把这个说出来:
function propertyByPath(object, path = '') {
if (/[,(){}&|;]/.test(path)) {
throw 'forbidden characters in path';
}
return Function(
...Object.keys(window).filter(k => window[k] instanceof Window || window[k] instanceof Document),
"obj",
`return ((o) => o${!path.startsWith('[') ? '.' : ''}${path})(...arguments, obj);`)
.bind(object)(object);
}
propertyByPath({ a: { b: 'hello1' } }, "a.b"); // prints 'hello1'
propertyByPath({ a: { b: 'hello2' } }, "['a']?.b"); // returns 'hello2'
propertyByPath({ a: { b: 'hello2' } }, "a.b;console.log()"); // throws exception
上面的代码在执行路径计算和屏蔽Window和Document对象(如果执行阻止不成功的话)的同时,努力防止代码执行。
我并不是说它是100%安全的(尽管我希望看到建议可能绕过的评论)也不是有效的,但在需要路径的灵活性(可选链等)以及一些缓解措施的情况下,它可能是合适的。