Почему эта троичная ошибка выдает ошибку, а не оценивается как ложная?

Я пытаюсь проверить истинность свойства объекта. Если оно существует и имеет значение, используйте это значение, а если его нет, добавьте значение по умолчанию к другому объекту.

const initNetwork = ( setupObj ) => {
    let obj = {};

    obj = Object.assign({}, setupObj);

    obj.eth0 = obj.eth0 ? obj.eth0 : {};
    obj.wlan0 = obj.wlan0 ? obj.wlan0 : {};

    obj.eth0.server = obj.eth0.server ? obj.eth0.server : {};
    obj.wlan0.client = obj.wlan0.client ? obj.wlan0.client : {};
    obj.wlan0.server = obj.wlan0.server? obj.wlan0.server : {};

    obj.eth0.mac = null;
    obj.wlan0.mac = null;

    obj.eth0.server.address = setupObj.eth0.server.address ? setupObj.eth0.server.address : "10.0.0.1";

}

initNetwork(); // intentionally leaving this empty to test setting default values.

Я получаю ошибку здесь, хотя. Я думал, что он вернет undefined и поэтому установит obj.eth0.server.address в ложное значение "10.0.0.1".

    obj.eth0.server.address = setupObj.eth0.server.address ? setupObj.eth0.server.address : "10.0.0.1";
                                       ^

TypeError: Cannot read property 'eth0' of undefined

Как лучше всего увидеть, существует ли эта пара ключ / значение на всем протяжении дерева, и если да, то использовать это значение, в противном случае установить значение false?

3 ответа

Решение

Вы присваиваете новый объект с именем obj так что ваш чек должен быть против obj,
В этой ситуации setupObj всегда будет undefined,
Вы можете добавить еще одно условие для setupObj с использованием && оператор:

obj.eth0.server.address = (setupObj && setupObj.eth0.server.address) ? setupObj.eth0.server.address : "10.0.0.1";

Конечно, рекомендуется проверять каждый уровень вложенных объектов.

Бегущий пример:

const initNetwork = ( setupObj ) => {
    let obj = {};

    obj = Object.assign({}, setupObj);

    obj.eth0 = obj.eth0 ? obj.eth0 : {};
    obj.wlan0 = obj.wlan0 ? obj.wlan0 : {};

    obj.eth0.server = obj.eth0.server ? obj.eth0.server : {};
    obj.wlan0.client = obj.wlan0.client ? obj.wlan0.client : {};
    obj.wlan0.server = obj.wlan0.server? obj.wlan0.server : {};

    obj.eth0.mac = null;
    obj.wlan0.mac = null;

    obj.eth0.server.address = (setupObj && setupObj.eth0.server.address) ? setupObj.eth0.server.address : "10.0.0.1";

}

initNetwork(); // intentionally leaving this empty to test setting default values.

Возможно, блок try / catch поможет вам избавиться от лишнего кода:

try {
    obj.eth0.server.address = setupObj.eth0.server.address;
} catch (e) {
    if (e instanceof TypeError) {
        obj.eth0.server.address = '10.0.0.1';
    } else {
        throw e;
    }
}

Вы можете проверить, существует ли объект, но вы не можете проверить, существует ли свойство несуществующего объекта, и именно это пытается делать ваш код, когда setupObj не передается в функцию.

Вам нужна ваша функция, чтобы проверить, был ли передан аргумент, прежде чем пытаться использовать этот аргумент. И, учитывая, что в вашем коде есть два места, где вам нужно выполнить этот тест, имеет больше смысла не использовать троичный и вместо этого использовать традиционный if,

Функция должна быть следующей (вы можете запустить этот код, чтобы увидеть его в действии):

const initNetwork = ( setupObj ) => {
    let obj = null;  // Don't set a value here because it's just going to be overridden

    // If setupObj exists....
    if(setupObj){
      // Use it:
      obj = Object.assign({}, setupObj);
      obj.eth0.server.address =  setupObj.eth0.server.address;
    } else {
      // But, if not, you need to set up your defaults:
      obj = {
         eth0: {
           server: {
             address: "10.0.0.1"
           },
           mac: null
         },
         wlan0 : {
            server: {},
            client: {},
            mac:null
         }
      };
    }
    
    // After that, you can proceed as you need to...
    
    // TEST:
    console.log(obj.eth0.server.address);
}

initNetwork(); // intentionally leaving this empty to test setting default values.

// Now a test for when a valid setupObj is passed:
var objTest = {
         eth0: {
           server: {
             address: "192.168.1.1"
           },
           mac: null
         },
         wlan0 : {
            server: {},
            client: {},
            mac:null
         }
      };

initNetwork(objTest);

Другие вопросы по тегам