Easy way to set javascript object multilevel property?

元气小坏坏 提交于 2019-12-04 12:41:10

No, there is no way to set "multilevel keys". You need to initialize each object before trying to add properties to it.

var allUserExpiry = {};
allUserExpiry[aData.userId] = {}
allUserExpiry[aData.userId][aData.courseId] = {}
allUserExpiry[aData.userId][aData.courseId][aData.uscId] = aData;

Or you can do it:

function setByPath(obj, path, value) {
    var parts = path.split('.');
    var o = obj;
    if (parts.length > 1) {
      for (var i = 0; i < parts.length - 1; i++) {
          if (!o[parts[i]])
              o[parts[i]] = {};
          o = o[parts[i]];
      }
    }

    o[parts[parts.length - 1]] = value;
}

And use:

setByPath(obj, 'path.path2.path', someValue);

This approach has many weak places, but for fun... :)

Why not just do this?

var allUserExpiry={};
allUserExpiry[aData.userId] = {aData.courseId: {aData.uscId: aData}};

Using Computed property names from ES6, it is possible to do:

var allUserExpiry = {
    [aData.userId] = {
        [aData.courseId]: {
            [aData.uscId]: aData
        }
    }
};

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer#Computed_property_names

I have a pretty hacky but short way of doing it in IE9+ as well as real browsers.

Given var path = 'aaa.bbb.ccc.ddd.eee'; where path is what your intending to make into an object and var result = {}; will will create the object {aaa: {bbb: {ccc: {ddd: {eee: {}}}}}

result = {}
path.split('.').reduce(function(prev, e) {
    var newObj = {};
    prev[e] = newObj;
    return newObj;
}, result);

will store the object in result.

How it works:

  • split('.') converts the input into ['aaa', 'bbb', 'ccc', 'ddd', 'eee']
  • reduce(function (...) {...}, result) runs through the array created by split, and for each entry will pass along a returned value to the next one. In our case we pass the new object through after adding the new object to the old one. This creates a chain of objects. reduce returns the last object you return inside of it, so we have to defined result beforehand.

This relies on using references so it won't be immediately clear how it works if you're expecting your code to be maintained by anyone else and should probably be avoided to be honest, but it works at least.

You can also use the following to create the initial structure:

var x = function(obj, keys) {
    if (!obj) return;

    var i, t;
    for (i = 0; i < keys.length; i++) {
        if (!t) {
            t = obj[keys[i]] = {};
        } else {
            t[keys[i]] = {};
            t = t[keys[i]];
        }
    }
};

var a = {}; 
x(a, ['A', 'B', 'C', 'D', 'E', 'F']);

Another approach without strings or array as argument.

function fillObject() {
  var o = arguments[0];
  for(var i = 1; i < arguments.length-1; i++) {
    if(!o.hasOwnProperty(arguments[i])) {
      o[arguments[i]] = {};
    }
    if(i < arguments.length-2) {
      o = o[arguments[i]];
    }else {
      o[arguments[i]] = arguments[i+1]
    }
  }
}

var myObj = {"foo":{}};

fillObject(myObj,"back","to","the","future",2);

console.log(JSON.stringify(myObj));
// {"foo":{},"back":{"to":{"the":{"future":2}}}}

But I wouldn't use it :-) It's just for fun. Because I don't like too much intelligent algorithm. (If it was in this category)

Using lodash you can do this easily (node exists and empty check for that node)..

var lodash = require('lodash-contrib');

function invalidateRequest(obj, param) {
    var valid = true;

    param.forEach(function(val) {
        if(!lodash.hasPath(obj, val)) {
            valid = false;
        } else {
            if(lodash.getPath(obj, val) == null || lodash.getPath(obj, val) == undefined || lodash.getPath(obj, val) == '') {
                valid = false;
            }
        }
    });
    return valid;
}

Usage:

leaveDetails = {
              "startDay": 1414998000000,
              "endDay": 1415084400000,
              "test": { "test1" : 1234 }

    };

    var validate;

    validate = invalidateRequest(leaveDetails, ['startDay', 'endDay', 'test.test1']);

it will return boolean.

Simply use loadash,

let object = {};
let property = "a.b.c";
let value = 1;
_.set(object, property, value); // sets property based on path
let value = _.get(object, property, default); // gets property based on path
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!