2010-10-17 17 views
16

Tengo la siguiente respuesta JSON de una solicitud ajax.Compruebe si se define un objeto, mejor práctica.

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 
}; 

La dosis no JSON siempre devuelven una propiedad "freeOfChargeProduct". Así que si quiero obtener el precio "freeOfChargeProduct", entonces tengo que hacer lo siguiente:

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

No hay problemas. Pero es muy molesto verificar cada propiedad en el objeto, así que creé una función que verifica si una propiedad en un objeto está definida.

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. 

Ahora a mi pregunta: ¿Es esta una manera buena o mala para comprobar si existe una propiedad de un objeto? ¿Alguna mejor sugerencia/método?

EDIT:

no wa no utilizar el & & -operator. Soy flojo y estoy buscando un método reutilizable para verificar si un objeto (o propiedad de un objeto) está definido.

:) ¡Gracias!

+1

Hace un tiempo tuve [una pregunta similar] (http://stackoverflow.com/questions/2631001/javascript-test-for-existence-of-nested-object-key). Es posible que le interesen algunas de las respuestas. – user113716

+0

¡Gracias por tu respuesta! Encontré una respuesta (publicada por Kennebec) y le di +1 :) – nekman

Respuesta

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

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

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

Esto funcionará para cualquier tipo de datos en JavaScript, incluso un número que sea cero. Si está buscando un objeto o una cadena, simplemente use x && x.y dentro de la instrucción if, o si ya sabe que x es un objeto, if(x.y) ...

19

Utilice el patrón de vigilancia:

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

Esto es cómo funciona el patrón de vigilancia.

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

La primera comprobación es "¿Tiene a existe la propiedad?". Si no, se ejecuta la rama else. En caso afirmativo, se produce la siguiente comprobación, que es "¿Tiene el objeto a la propiedad b?". Si no, se ejecuta la rama else. En caso afirmativo, se produce la verificación final: "¿El objeto a.b contiene la propiedad c?". Si no, se ejecuta la rama else. Si es así (y solo entonces), se ejecuta la rama if.

Actualización: ¿Por qué se llama "patrón de protección"?

var value = a && b; 

En este ejemplo, el miembro de b (el operando de la derecha) es vigilado por el operador &&. Solo si el miembro a (el operando de la izquierda) es verdadero ("digno"), solo se devuelve el miembro b. Sin embargo, si el miembro a es falso ("no digno"), se devuelve.

Por cierto, los miembros son Falsy si regresan estos valores: null, undefined, 0, "", false, NaN. Los miembros son veraces en todos los demás casos.

+9

¿Lo llamas guardia? Lo llamo lógico Y ... nunca había escuchado antes de * operador de guardia *, pero ¿alguien podría indicarme una fuente? –

+0

Sí, puedo usar el operador && -. Pero quiero usar una solución común que pueda volver a usar para cualquier objeto. – nekman

+0

Guardia es su apodo. (Porque guarda el segundo operando: si el primer operando es falso, devuelve el primer operando. Si el primer operando es verdadero, devuelve el segundo operando). –

0

Se podría hacer algo como esto:

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... 
} 

Se generaría un mensaje de este tipo a partir de los datos proporcionados en su pregunta si los campos existe:

Usted recibe 6 de XYZ por sólo $ 277,5, Ahorras $ 55.5

Si los datos no existen, terminarás en el bloque catch. Siempre se puede intentar Try, Catch, Forget aquí si no se puede encontrar una manera de manejar el error (¿Tal vez hacer una nueva solicitud AJAX para los datos?).

1

Esto no es un problema de sintaxis ya que es un problema de diseño.

Pregunta A. * ¿Tiene el control del servidor json?

Si la respuesta a esto es no, lo cual supongo, la situación será todo en el cliente.

Por favor, lea esto: http://martinfowler.com/eaaDev/PresentationModel.html

Como el servidor es la fuente, en este caso se proporcionará el modelo. Este patrón especifica un artefacto adicional: el modelo de presentación (PM). En Javascript sugiero dos artefactos, uno adicional para el código del convertidor.

De acuerdo con este patrón de diseño, el PM es responsable de convertir el modelo al PM, y viceversa si es necesario. En su caso, nunca ocurrirá una conversión de PM a M.

Esto significa que un objeto js tiene un método o constructor que digiere el modelo y lo traduce a sí mismo, con la ayuda del convertidor (a continuación).

Hacer esto puede acabar con un PM con este aspecto:

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

enter code here this.getFreeOfCharge = function() {} ... this.fromModel = function (jsonEntry, convertidor) {// convertir esto con el convertidor;) a una visión específica para este OrderlinePM utilizable // también inwith ... } "orderLineId": 0, "totalOrderLinePrice": "741.36", "t otalOrderPrice ":" 1,314.92 ", " totalQty ": 17 };

función mySpecialFunctionPMConvertor { this.fromModel = functiono() {... // hacer cosas extrañas con el modelo y poulate un PM con él. }}

Ok, dejar de tratar de código de formato en este editor de texto enriquecido :(

  • Puede tener varios PM:. S para tareas diffrent todo dependiendo del mismo objeto modelo
  • Además esto hará que el objeto convertidor comprobable en algo que podría ser ejecutado de forma automática .... err bien maby manualmente, pero de todos modos.

Así que el problema del código reflexión engorroso no es realmente un proble metro. Pero la cohesión es un problema, expesialmente en JavaScript.

Cuestiones relacionadas