Проверка работоспособности объекта JSON

Снова и снова мне приходится иметь дело с кодом, как рассмотрим следующий гипотетический пример:

if (node.data.creatures.humans.women.number === Infinity) {
  // do-someting
}

Теперь проблема в том, что если узел не определен, это условие будет нарушено. Точно так же он сломается, если node.data не определен, node.data.creatures не определен и так далее.

В итоге я использую следующие длинные условия:

if (node && node.data && node.data.creatures && node.data.creatures.humans && node.data.creatures.women && node.data.creatures.humans.women.number === Infinity) {
  // do-someting
}

Теперь представьте, что мне нужно использовать части этого объекта JSON и во многих других частях кода.

Код вдруг начинает выглядеть очень некрасиво. Есть ли лучший способ избежать ошибок типа "Не удается вызвать свойство неопределенного" из-за первого условия, о котором я упомянул, чтобы код тоже выглядел лучше.

Как вы справляетесь с такими ситуациями?

3 ответа

Вот то, что я использую, возможно, это не "оптимизирующий" способ, но, который работает для меня:

walkObject = function(obj, path) {
  var i = 0,
    part = void 0,
    parts = path.split('.');

  while (obj && (part = parts[i++])) {
    obj = obj[part];
  }
  return obj;
};

Метод принимает объект и строку, содержащую точечную запись свойства, которое вы хотите проверить:

// the object
var obj = { a: { b: {c: [1,2,3], d: "aa"} } };

// tests
console.log("a,b,c", walkObject(obj, 'a.b.c')); // [1,2,3]
console.log("a,b,e", walkObject(obj, 'a.b.e')); // undefined
console.log("z,b,e", walkObject(obj, 'z.b.e')); // undefined

Пытаясь получить доступ к собственности на undefined ловимый TypeErrorтак что вы можете использовать try..catch:

try {
    if (node.data.creatures.humans.women.number === Infinity) {
        // do something
    }
} catch (e) {
    // property doesn't exist
}

Вы можете обернуть потенциально опасные части try - catch:

try {
    if (node.data.creatures.humans.women.number === Infinity) {
        // do-someting
    }
} catch () {
    console.log(e);
}

Другой способ и, возможно, более элегантный - определить ожидаемую структуру объекта и объединить ее с фактическими данными, используя, например, jQuery.extend ().

var nodeTemplate = {
    data: {
        creatures: {
            humans: {...}
        }
    }
}

Это позволит убедиться, что структура соответствует вашим ожиданиям, а несуществующие поля имеют некоторые значения по умолчанию.

Затем объедините это:

node = $.extend(nodeTemplate, node);
Другие вопросы по тегам