Подтвердить что ты не робот

Проверьте, определен ли объект, лучшая практика.

У меня есть следующий ответ JSON от ajax-запроса.

var json = {
    "response": {
        "freeOfChargeProduct": {  
        "description": "Product",  
        "orderQty": 5,
        "productName": "XYZ",
        "qty": 6,
        "details": {
            "price": 55.5, 
            "instock": "true",
            "focQuantity": 1
        }
    }, 
    "orderLineId": 4788,
    "totalOrderLinePrice": "741.36",
    "totalOrderPrice": "1,314.92",
    "totalQty": 17
};

JSON не всегда возвращает свойство "freeOfChargeProduct". Поэтому, если я хочу получить цену "freeOfChargeProduct", я должен сделать следующее:

var getFreeOfChargeProductPrice = function() { 
   var r = json.response;
   if (r && r.freeOfChargeProduct && r.freeOfChargeProduct.details) {
      return r.freeOfChargeProduct.details.price;         
   }
   return null;
};

Нет проблем. Но очень раздражает проверять каждое свойство объекта, поэтому я создал функцию, которая проверяет, определено ли свойство в объекте.

var getValue = function (str, context) {
    var scope = context || window,
        properties = str.split('.'), i;
    for(i = 0; i < properties.length; i++) {
      if (!scope[properties[i]]) {                       
         return null;
      } 
      scope = scope[properties[i]];        
    }
    return scope;
};

var price = getValue('json.response.freeOfChargeProduct.details.price');
// Price is null if no such object exists.

Теперь на мой вопрос: Является ли это хорошим или плохим способом проверить, существует ли свойство в объекте? Любые лучшие предложения/методы?

EDIT:

Я не хочу использовать & -оператор. Я ленив, и я ищу метод повторного использования, чтобы проверить, определен ли объект (или свойство объекта).

:) Спасибо!

4b9b3361

Ответ 1

if(x && typeof x.y != 'undefined') {
    ...
}

// or better
function isDefined(x) {
    var undefined;
    return x !== undefined;
}

if(x && isDefined(x.y)) {
    ...
}

Это будет работать для любого типа данных в JavaScript, даже для числа, которое равно нулю. Если вы проверяете объект или строку, просто используйте x && x.y в инструкции if, или если вы уже знаете, что x является объектом, if(x.y) ...

Ответ 2

Используйте шаблон защиты:

if (json.response && json.response.freeOfChargeProduct && json.response.freeOfChargeProduct.details) {
    // you can safely access the price
}  

Вот как работает шаблон защиты.

if (a && a.b && a.b.c) { ... } else { ... }

Первая проверка: "Существует ли свойство a?". Если нет, else-branch выполняется. Если да, то происходит следующая проверка: "Объект a содержит свойство b?". Если нет, выполняется else-branch. Если да, то происходит окончательная проверка: "Объект a.b содержит свойство c?". Если нет, выполняется else-branch. Если да (и только тогда), выполняется if-ветвь.

Обновление: почему он называется "шаблон защиты"?

var value = a && b;  

В этом примере элемент b (правый операнд) охраняется оператором &&. Только если член a (левый операнд) правдивый ( "достойный" ), то возвращается только член b. Если, однако, член a является ложным ( "недостоин" ), то он сам возвращается.

BTW, члены являются ложными, если они возвращают эти значения: null, undefined, 0, "", false, NaN. Члены являются правдивыми во всех других случаях.

Ответ 3

Это не проблема синтаксиса, поскольку это проблема с шаблоном проектирования.

Вопрос А. * У вас есть контроль над json-сервером?

Если ответ на этот вопрос отрицательный, я предполагаю, что все будет на клиенте.

Прочтите следующее: http://martinfowler.com/eaaDev/PresentationModel.html

Поскольку сервер является источником, в этом случае он предоставит модель. Этот шаблон указывает дополнительный артефакт: модель представления (PM). В javascript я бы предложил два артефакта, дополнительный для кода конвертера.

В соответствии с этим шаблоном проектирования PM отвечает за преобразование модели в PM и, при необходимости, обратно. В вашем случае не будет никакого преобразования из PM в M.

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

Выполняя это, вы получите PM, похожий на это:

var OrderlinePM = {
  "hasFreeOfCharge": false | true,
  "freeOfCharge" : {...}

enter code here this.getFreeOfCharge = function() {...  }  this.fromModel = function (jsonEntry, convertor) { // конвертируем это с конвертером;) в для этого конкретного вида, используемого OrderlinePM // также inwith...  }   "OrderLineId": 0,   "TotalOrderLinePrice": "741,36",   "TotalOrderPrice": "1,314.92",   "TotalQty": 17 };

функция mySpecialFunctionPMConvertor {  this.fromModel = functiono() {...//делать странные вещи с моделью и пула PM с ней.  } }

Хорошо, я отказываюсь от форматирования кода в этом богатом текстовом редакторе: (

  • У вас может быть несколько PM: s для разных задач в зависимости от одного и того же объекта модели.
  • Кроме того, это сделает объект-конвертер тестируемым в чем-то, что может быть выполнено автоматически.... err ok maby вручную, но в любом случае.

Таким образом, проблема громоздкого кода отражения действительно не проблема. Но сплоченность - это проблема, особенно в JavaScript.

Ответ 4

Вы можете сделать что-то вроде этого:

try{
    var focp = json.response.freeOfChargeProduct
    var text = "You get " + focp.qty + " of " +
        focp.productName +
        " for only $" + (focp.qty-focp.details.focQuantity)*focp.details.price +
        ", You save $" + focp.details.focQuantity*focp.details.price;
    $("order_info").innerText = text;
} catch(e) {
    // woops, handle error...
}

Он генерирует такое сообщение из предоставленных данных в вашем вопросе, если поля существуют:

Вы получаете 6 из XYZ всего за $277,5, вы экономите $55.5

Если данные не существуют, вы попадете в блок catch. Вы всегда можете просто попробовать Try, Catch, Forget, если вы не можете найти способ справиться с ошибкой (может быть, сделать новый запрос AJAX для данных?).