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… 循环遍历数组,但我还没有找到创建嵌套对象的方法。

如果你已经走到这一步,非常感谢你花时间阅读,即使你帮不上忙。

原文由 David 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 450
2 个回答
function assign(obj, keyPath, value) {
   lastKeyIndex = keyPath.length-1;
   for (var i = 0; i < lastKeyIndex; ++ i) {
     key = keyPath[i];
     if (!(key in obj)){
       obj[key] = {}
     }
     obj = obj[key];
   }
   obj[keyPath[lastKeyIndex]] = value;
}

用法:

 var settings = {};
assign(settings, ['Modules', 'Video', 'Plugin'], 'JWPlayer');

原文由 kennytm 发布,翻译遵循 CC BY-SA 4.0 许可协议

放入一个函数,简短而快速(无递归)。

 var createNestedObject = function( base, names ) {
    for( var i = 0; i < names.length; i++ ) {
        base = base[ names[i] ] = base[ names[i] ] || {};
    }
};

// Usage:
createNestedObject( window, ["shapes", "triangle", "points"] );
// Now window.shapes.triangle.points is an empty object, ready to be used.

它跳过层次结构中已经存在的部分。如果您不确定层次结构是否已创建,则很有用。

或者:

一个更高级的版本,您可以直接将值分配给层次结构中的最后一个对象,并且您可以链接函数调用,因为它返回最后一个对象。

 // Function: createNestedObject( base, names[, value] )
//   base: the object on which to create the hierarchy
//   names: an array of strings contaning the names of the objects
//   value (optional): if given, will be the last object in the hierarchy
// Returns: the last object in the hierarchy
var createNestedObject = function( base, names, value ) {
    // If a value is given, remove the last name and keep it for later:
    var lastName = arguments.length === 3 ? names.pop() : false;

    // Walk the hierarchy, creating new objects where needed.
    // If the lastName was removed, then the last object is not set yet:
    for( var i = 0; i < names.length; i++ ) {
        base = base[ names[i] ] = base[ names[i] ] || {};
    }

    // If a value was given, set it to the last name:
    if( lastName ) base = base[ lastName ] = value;

    // Return the last object in the hierarchy:
    return base;
};

// Usages:

createNestedObject( window, ["shapes", "circle"] );
// Now window.shapes.circle is an empty object, ready to be used.

var obj = {}; // Works with any object other that window too
createNestedObject( obj, ["shapes", "rectangle", "width"], 300 );
// Now we have: obj.shapes.rectangle.width === 300

createNestedObject( obj, "shapes.rectangle.height".split('.'), 400 );
// Now we have: obj.shapes.rectangle.height === 400

注意:如果您的层次结构需要从标准对象以外的值构建(即不是 {} ),另请参阅下面的 TimDog 的回答。

编辑:使用常规循环而不是 for...in 循环。在库修改 Array 原型的情况下更安全。

原文由 jlgrall 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题