How to avoid 'cannot read property of undefined' errors?

前端 未结 16 2199
野性不改
野性不改 2020-11-22 06:02

In my code, I deal with an array that has some entries with many objects nested inside one another, where as some do not. It looks something like the following:



        
相关标签:
16条回答
  • 2020-11-22 06:19

    This is a common issue when working with deep or complex json object, so I try to avoid try/catch or embedding multiple checks which would make the code unreadable, I usually use this little piece of code in all my procect to do the job.

    /* ex: getProperty(myObj,'aze.xyz',0) // return myObj.aze.xyz safely
     * accepts array for property names: 
     *     getProperty(myObj,['aze','xyz'],{value: null}) 
     */
    function getProperty(obj, props, defaultValue) {
        var res, isvoid = function(x){return typeof x === "undefined" || x === null;}
        if(!isvoid(obj)){
            if(isvoid(props)) props = [];
            if(typeof props  === "string") props = props.trim().split(".");
            if(props.constructor === Array){
                res = props.length>1 ? getProperty(obj[props.shift()],props,defaultValue) : obj[props[0]];
            }
        }
        return typeof res === "undefined" ? defaultValue: res;
    }
    
    0 讨论(0)
  • 2020-11-22 06:19

    If you have lodash you can use its .get method

    _.get(a, 'b.c.d.e')
    

    or give it a default value

    _.get(a, 'b.c.d.e', default)
    
    0 讨论(0)
  • 2020-11-22 06:20

    If you are using lodash, you could use their "has" function. It is similar to the native "in", but allows paths.

    var testObject = {a: {b: {c: 'walrus'}}};
    if(_.has(testObject, 'a.b.c')) {
      //Safely access your walrus here
    }
    
    0 讨论(0)
  • 2020-11-22 06:20

    Try this. If a.b is undefined, it will leave the if statement without any exception.

    if (a.b && a.b.c) {
      console.log(a.b.c);
    }
    
    0 讨论(0)
  • 2020-11-22 06:20

    Lodash has a get method which allows for a default as an optional third parameter, as show below:

    const myObject = {
      has: 'some',
      missing: {
        vars: true
      }
    }
    const path = 'missing.const.value';
    const myValue = _.get(myObject, path, 'default');
    console.log(myValue) // prints out default, which is specified above
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>

    0 讨论(0)
  • 2020-11-22 06:20

    I answered this before and happened to be doing a similar check today. A simplification to check if a nested dotted property exists. You could modify this to return the value, or some default to accomplish your goal.

    function containsProperty(instance, propertyName) {
        // make an array of properties to walk through because propertyName can be nested
        // ex "test.test2.test.test"
        let walkArr = propertyName.indexOf('.') > 0 ? propertyName.split('.') : [propertyName];
    
        // walk the tree - if any property does not exist then return false
        for (let treeDepth = 0, maxDepth = walkArr.length; treeDepth < maxDepth; treeDepth++) {
    
            // property does not exist
            if (!Object.prototype.hasOwnProperty.call(instance, walkArr[treeDepth])) {
                return false;
            }
    
            // does it exist - reassign the leaf
            instance = instance[walkArr[treeDepth]];
    
        }
    
        // default
        return true;
    
    }
    

    In your question you could do something like:

    let test = [{'a':{'b':{'c':"foo"}}}, {'a': "bar"}];
    containsProperty(test[0], 'a.b.c');
    
    0 讨论(0)
提交回复
热议问题