该函数采用a.b.c
之类的输入路径,并应输出嵌套结构json,如:
{
a: {
b: {
c: {}
}
}
}
使用迭代样式的算法是:
function stringToObj(path, obj) {
var parts = path.split(".");
var part;
while ((part = parts.shift())) {
if (typeof obj[part] != "object") obj[part] = {};
obj = obj[part]; // line 6
}
}
当前用法:
let result = {};
stringToObj("a.b.c", result);
console.log(result); // outputs the json
它依赖于在第6行上更改obj参数。我不想不依赖传递result
对象,而是在函数内部创建一个对象。这样做会导致不同的结果。所需的示例用法:
const result = stringToObj("a.b.c"); // result should be the json
该练习仅供学习。主要目的是理解为什么按以下步骤删除obj
并重写函数无法按预期工作:
function stringToObj(path) {
var obj = {};
var parts = path.split(".");
var part;
while ((part = parts.shift())) {
if (typeof obj[part] != "object") obj[part] = {};
obj = obj[part]; // line 6
}
return obj;
}
除以.
后,可以使用reduceRight
从最后一个属性c
开始,同时获取一个空对象的初始值。在回调内部,使用计算属性返回一个新对象,该对象包含正在迭代的属性处的旧对象:
const stringToObj = str => str.split('.').reduceRight(
(lastObj, prop) => ({ [prop]: lastObj }), {}
);
console.log(stringToObj('a.b.c'));
如果您不熟悉它,则reduceRight
类似于reduce
,不同之处在于它从数组的最后一个元素开始并向后进行迭代,而不是从数组的第一个元素开始并向后进行迭代。在每次迭代中,都会调用回调,其中第一个参数(此处为lastObj
)是last迭代返回的值,第二个参数是要迭代的数组的当前项。
您还可以reverse
属性数组并使用reduce
而不是reduceRight
,这乍一看可能会更容易理解,但是它不太优雅:
const stringToObj = str => str.split('.').reverse().reduce(
(lastObj, prop) => ({ [prop]: lastObj }), {}
);
console.log(stringToObj('a.b.c'));
也请不要混合使用var
和let
。如果要使用ES2015语法-您应使用-考虑始终使用const
,而仅使用let
when you must reassign。永远不要使用var
,它有太多陷阱值得在现代代码中使用。