Javascript:如何使用数组给出的对象名称动态创建嵌套对象
我希望有人能帮我解决这个 JavaScript 问题。
我有一个名为“设置”的对象,我想编写一个向该对象添加新设置的函数。
新设置的名称和值以字符串形式提供。然后,给出设置名称的字符串被下划线分割成一个数组。新设置应添加到现有的“设置”对象中,方法是使用数组每个部分指定的名称创建新的嵌套对象,最后一部分除外,它应该是给出设置值的字符串。然后我应该能够参考该设置并例如提醒其值。我可以像这样以静态方式执行此操作...
var Settings = {};
var newSettingName = "Modules_Video_Plugin";
var newSettingValue = "JWPlayer";
var newSettingNameArray = newSettingName.split("_");
Settings[newSettingNameArray[0]] = {};
Settings[newSettingNameArray[0]][newSettingNameArray[1]] = {};
Settings[newSettingNameArray[0]][newSettingNameArray[1]][newSettingNameArray[2]] = newSettingValue;
alert(Settings.Modules.Mediaplayers.Video.Plugin);
...创建嵌套对象的部分正在执行此操作...
Settings["Modules"] = {};
Settings["Modules"]["Video"] = {};
Settings["Modules"]["Video"]["Plugin"] = "JWPlayer";
但是,由于构成设置名称的部分数量可能会有所不同,例如 newSettingName 可能是“Modules_Floorplan_Image_Src”,我想使用诸如...之类的函数动态执行此操作,
createSetting (newSettingNameArray, newSettingValue);
function createSetting(setting, value) {
// code to create new setting goes here
}
任何人都可以帮助我弄清楚如何动态执行此操作?
我认为其中必须有一个 for...循环来遍历数组,但我无法找到创建嵌套对象的方法。
如果您已经读到这里,非常感谢您花时间阅读,即使您帮不上忙。
I hope someone can help me with this Javascript.
I have an Object called "Settings" and I would like to write a function that adds new settings to that object.
The new setting's name and value are provided as strings. The string giving the setting's name is then split by the underscores into an array. The new setting should get added to the existing "Settings" object by creating new nested objects with the names given by each part of the array, except the last part which should be a string giving the setting's value. I should then be able to refer to the setting and e.g. alert its value. I can do this in a static way like this...
var Settings = {};
var newSettingName = "Modules_Video_Plugin";
var newSettingValue = "JWPlayer";
var newSettingNameArray = newSettingName.split("_");
Settings[newSettingNameArray[0]] = {};
Settings[newSettingNameArray[0]][newSettingNameArray[1]] = {};
Settings[newSettingNameArray[0]][newSettingNameArray[1]][newSettingNameArray[2]] = newSettingValue;
alert(Settings.Modules.Mediaplayers.Video.Plugin);
... the part that creates the nested objects is doing this ...
Settings["Modules"] = {};
Settings["Modules"]["Video"] = {};
Settings["Modules"]["Video"]["Plugin"] = "JWPlayer";
However, as the number of parts that make up the setting name can vary, e.g. a newSettingName could be "Modules_Floorplan_Image_Src", I'd like to do this dynamically using a function such as...
createSetting (newSettingNameArray, newSettingValue);
function createSetting(setting, value) {
// code to create new setting goes here
}
Can anyone help me work out how to do this dynamically?
I presume there has to be a for...loop in there to itterate through the array, but I haven't been able to work out a way to create the nested objects.
If you've got this far thanks very much for taking the time to read even if you can't help.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(26)
放入一个函数,短而快(无递归)。
它会跳过层次结构中已经存在的部分。如果您不确定层次结构是否已创建,则很有用。
或者:
一个更高级的版本,您可以直接将值分配给层次结构中的最后一个对象,并且可以链接函数调用,因为它返回最后一个对象。
注意:如果您的层次结构需要从标准对象以外的值(即不是
{}
)构建,另请参阅下面 TimDog 的回答。编辑:使用常规循环而不是
for...in
循环。在库修改数组原型的情况下更安全。Put in a function, short and fast (no recursion).
It skips already existing parts of the hierarchy. Useful if you are not sure whether the hierarchy was already created.
Or:
A fancier version where you can directly assign the value to the last object in the hierarchy, and you can chain function calls because it returns the last object.
Note: if your hierarchy needs to be built from values other that standard objects (ie. not
{}
), see also TimDog's answer below.Edit: uses regular loops instead of
for...in
loops. It's safer in cases where a library modifies the Array prototype.用法:
Usage:
我的 ES2015 解决方案。保留现有价值观。
例子:
My ES2015 solution. Keeps existing values.
Example:
使用 ES6 可以缩短时间。将路径设置为数组。
首先,您必须反转数组,才能开始填充对象。
Using ES6 is shorten. Set your path into an array.
first, you have to reverse the array, to start filling the object.
另一种递归解决方案:
用法示例:
Another recursive solution:
Example usage:
我喜欢这种在嵌套字段上设置特定值的 ES6 不可变方式:
然后使用它来创建目标对象。
I love this ES6 immutable way to set certain value on nested field:
And then use it with creating your target object.
Lodash 有一个 _.set 方法来实现此目的
Lodash has a _.set method to achieve this
这是对 jlggrall 答案的一个简单调整,允许在嵌套层次结构中的每个元素上设置不同值:
希望它有所帮助。
Here is a simple tweak to jlgrall's answer that allows setting distinct values on each element in the nested hierarchy:
Hope it helps.
这是动态创建嵌套对象的功能解决方案。
例子:
Here is a functional solution to dynamically create nested objects.
Example:
受到 ImmutableJS setIn 方法的启发,该方法永远不会改变原始方法。这适用于混合数组和对象嵌套值。
Inspired by ImmutableJS setIn method which will never mutate the original. This works with mixed array and object nested values.
感谢这个问题是非常古老的!但是在遇到需要在 Node 中执行类似操作后,我制作了一个模块并将其发布到 npm。
Nestob
Appreciate that this question is mega old! But after coming across a need to do something like this in node, I made a module and published it to npm.
Nestob
在循环中,您可以使用 lodash.set 并为您创建路径:
Inside your loop you can use
lodash.set
and will create the path for you:尝试使用递归函数:
try using recursive function:
我认为,这更短:
I think, this is shorter:
我发现 @jlgrall 的答案很好,但简化后,它在 Chrome 中不起作用。如果有人想要精简版,这是我的修复:
我希望这是有用且相关的。抱歉,我刚刚把这个例子搞砸了......
I found @jlgrall's answer was great but after simplifying it, it didn't work in Chrome. Here's my fixed should anyone want a lite version:
I hope this is useful and relevant. Sorry, I've just smashed this example out...
您可以定义自己的对象方法;为了简洁起见,我还使用下划线:
示例用法:
You can define your own Object methods; also I'm using underscore for brevity:
Sample usage:
为那些需要创建嵌套对象并支持数组键以将值设置为路径末尾的人提供的代码片段。路径是如下字符串:
modal.product.action.review.2.write.survey.data
。基于jlgrall版本。A snippet for those who need to create a nested objects with support of array keys to set a value to the end of path. Path is the string like:
modal.product.action.review.2.write.survey.data
. Based on jlgrall version.设置嵌套数据:
获取嵌套数据:
Set Nested Data:
Get Nested Data:
试试这个:https://github.com/silkyland/object-to-formdata
结果 :
Try this: https://github.com/silkyland/object-to-formdata
Result :
下面是几个有用函数的分解,每个函数都保存现有数据。不处理数组。
setDeep
:回答问题。对对象中的其他数据无损。setDefaultDeep
:相同,但仅在尚未设置时设置。setDefault
:如果尚未设置,则设置一个键。与 Python 的setdefault
相同。setStructure
:构建路径的辅助函数。我不确定为什么有人会想要字符串路径:
Here is a decomposition to several useful functions, that each preserve existing data. Does not handle arrays.
setDeep
: Answers question. Non-destructive to other data in the object.setDefaultDeep
: Same, but only sets if not already set.setDefault
: Sets a key if not already set. Same as Python'ssetdefault
.setStructure
: Helper function that builds the path.I'm not sure why anyone would want string paths:
由于我从本页开始,所以我想回馈
其他示例,即使它已设置,其他示例也会覆盖最终节点,而这不是我想要的。
另外,如果
returnObj
设置为true,它会返回基础对象。默认情况下,falsy
,它返回最深的节点。您还可以执行将数字键放置在数组中的操作(如果它们尚不存在)。请注意,数字键不会转换为路径第一个元素的数组,因为它是由基础对象的类型设置的。
当然,当数字键大于 0 时,您可能会看到一些
未定义
间隙。实际用途可能是
Since I started with something from this page, I wanted to contribute back
Other examples overwrote the final node even if it was set, and that wasn't what I wanted.
Also, if
returnObj
is set to true, it returns the base object. By default,falsy
, it returns the deepest node.You can also do something where numeric keys are placed in arrays (if they don't already exist). Note that numeric keys won't convert to arrays for the first element of the path, since that's set by the type of your base-object.
Naturally, when the numeric keys are greater than 0, you might see some
undefined
gaps.Practical uses of this might be
用法
Usage
简单的答案。在 es6 上,我使用此
示例 json,
您可以添加新密钥
,如下所示
simple answer. on es6, im using this
example json
you can add new key
and you get like bellow
接下来是 TimDog 的回答,这只会为最后一个元素增加价值
结果:
Followed by TimDog's answer this adds value to last element only
Result:
Eval 可能有点矫枉过正,但结果很容易可视化,没有嵌套循环或递归。
基本上,您正在逐步编写字符串
"obj['one']= {}", "obj['one']['two']"= {}
并对其进行评估;Eval is probably overkill but the result is simple to visualize, with no nested loops or recursion.
Basically you are progressively writing a string
"obj['one']= {}", "obj['one']['two']"= {}
and evaling it;