Detectar una propiedad de objeto indefinida

Resuelto Matt Sheppard asked hace 16 años • 49 respuestas

¿Cómo verifico si la propiedad de un objeto en JavaScript no está definida?

Matt Sheppard avatar Aug 26 '08 14:08 Matt Sheppard
Aceptado

La forma habitual de comprobar si el valor de una propiedad es el valor especial undefined, es:

if(o.myProperty === undefined) {
  alert("myProperty value is the special value `undefined`");
}

Para comprobar si un objeto no tiene realmente dicha propiedad y, por lo tanto, volverá undefinedde forma predeterminada cuando intente acceder a él:

if(!o.hasOwnProperty('myProperty')) {
  alert("myProperty does not exist");
}

Para comprobar si el valor asociado a un identificador es el valor especial undefined, o si ese identificador no ha sido declarado:

if(typeof myVariable === 'undefined') {
  alert('myVariable is either the special value `undefined`, or it has not been declared');
}

Nota: este último método es la única forma de hacer referencia a un identificador no declarado sin un error temprano, lo cual es diferente a tener un valor de undefined.

En versiones de JavaScript anteriores a ECMAScript 5, la propiedad denominada "indefinido" en el objeto global se podía escribir y, por lo tanto, una simple verificación foo === undefinedpodría comportarse inesperadamente si se hubiera redefinido accidentalmente. En JavaScript moderno, la propiedad es de solo lectura.

Sin embargo, en JavaScript moderno, "indefinido" no es una palabra clave, por lo que las variables dentro de las funciones pueden denominarse "indefinido" y ocultar la propiedad global.

Si le preocupa este (improbable) caso límite, puede utilizar el operador void para obtener el undefinedvalor especial en sí:

if(myVariable === void 0) {
  alert("myVariable is the special value `undefined`");
}
 avatar Jan 06 '2009 12:01

Creo que hay varias respuestas incorrectas a este tema. Contrariamente a la creencia común, "indefinido" no es una palabra clave en JavaScript y, de hecho, se le puede asignar un valor.

Código correcto

La forma más sólida de realizar esta prueba es:

if (typeof myVar === "undefined")

Esto siempre devolverá el resultado correcto e incluso maneja la situación en la que myVarno se declara.

Código degenerado. NO UTILICE.

var undefined = false;  // Shockingly, this is completely legal!
if (myVar === undefined) {
    alert("You have been misled. Run away!");
}

Además, myVar === undefinedgenerará un error en la situación en la que myVar no esté declarado.

MarkPflug avatar Aug 23 '2010 18:08 MarkPflug

Muchas respuestas aquí son vehementes en recomendar typeof, pero typeof es una mala elección . Nunca debe usarse para verificar si las variables tienen el valor undefined, porque actúa como una verificación combinada del valor undefinedy de si existe una variable. En la gran mayoría de los casos, usted sabe cuándo existe una variable y typeofsolo introducirá la posibilidad de una falla silenciosa si comete un error tipográfico en el nombre de la variable o en el literal de cadena 'undefined'.

var snapshot = …;

if (typeof snaposhot === 'undefined') {
    //         ^
    // misspelled¹ – this will never run, but it won’t throw an error!
}
var foo = …;

if (typeof foo === 'undefned') {
    //                   ^
    // misspelled – this will never run, but it won’t throw an error!
}

Entonces, a menos que esté realizando una detección de características², donde existe incertidumbre sobre si un nombre determinado estará dentro del alcance (como verificar typeof module !== 'undefined'como un paso en el código específico de un entorno CommonJS), typeofes una opción dañina cuando se usa en una variable, y la opción correcta es para comparar el valor directamente:

var foo = …;

if (foo === undefined) {
    ⋮
}

Algunos conceptos erróneos comunes sobre esto incluyen:

  • que la lectura de una variable "no inicializada" ( var foo) o parámetro ( function bar(foo) { … }, llamado como bar()) fallará. Esto simplemente no es cierto: las variables sin inicialización explícita y los parámetros a los que no se les asignaron valores siempre se convierten en undefined, y siempre están dentro del alcance.

  • que undefinedse puede sobrescribir. Es cierto que undefinedno es una palabra clave, pero es de sólo lectura y no configurable. Hay otras funciones integradas que probablemente no evites a pesar de que no son palabras clave ( Object, Math, NaN...) y el código práctico generalmente no está escrito en un entorno activamente malicioso, por lo que esta no es una buena razón para preocuparse undefined. (Pero si estás escribiendo un generador de código, no dudes en utilizarlo void 0).

Una vez aclarado cómo funcionan las variables, es hora de abordar la pregunta real: las propiedades de los objetos. No hay ninguna razón para usarlo alguna vez typeofpara las propiedades del objeto. La excepción anterior con respecto a la detección de características no se aplica aquí; typeofsolo tiene un comportamiento especial en las variables y las expresiones que hacen referencia a las propiedades del objeto no son variables.

Este:

if (typeof foo.bar === 'undefined') {
    ⋮
}

siempre es exactamente equivalente a esto³:

if (foo.bar === undefined) {
    ⋮
}

y teniendo en cuenta los consejos anteriores, para evitar confundir a los lectores sobre por qué está usando typeof, porque tiene más sentido usarlo ===para verificar la igualdad, porque podría refactorizarse para verificar el valor de una variable más adelante y porque simplemente se ve mejor, siempre deberías usar === undefined³ aquí también .

Otra cosa a considerar cuando se trata de propiedades de objetos es si realmente desea verificarlas undefined. Un nombre de propiedad determinado puede estar ausente en un objeto (produciendo el valor undefinedcuando se lee), presente en el objeto mismo con el valor undefined, presente en el prototipo del objeto con el valor undefined, o presente en cualquiera de aquellos sin undefinedvalor. 'key' in objle dirá si una clave está en algún lugar de la cadena prototipo de un objeto y Object.prototype.hasOwnProperty.call(obj, 'key')le dirá si está directamente en el objeto. Sin embargo, no entraré en detalles en esta respuesta sobre prototipos y el uso de objetos como mapas con clave de cadena, porque su objetivo principal es contrarrestar todos los malos consejos en otras respuestas, independientemente de las posibles interpretaciones de la pregunta original. ¡ Lea sobre prototipos de objetos en MDN para obtener más información!

¹ ¿Elección inusual de nombre de variable de ejemplo? Este es un código muerto real de la extensión NoScript para Firefox.
Sin embargo, no asuma que no saber lo que está dentro del alcance está bien en general. Vulnerabilidad adicional causada por abuso del alcance dinámico: Proyecto Zero 1225
, asumiendo una vez más un entorno ES5+ y que undefinedse refiere a la undefinedpropiedad del objeto global.

Ry- avatar Feb 26 '2014 21:02 Ry-

En JavaScript hay nulo y no definido . Tienen diferentes significados.

  • indefinido significa que el valor de la variable no se ha definido; No se sabe cuál es el valor.
  • nulo significa que el valor de la variable está definido y establecido en nulo (no tiene valor).

Marijn Haverbeke afirma, en su libro gratuito en línea " Eloquent JavaScript " (el énfasis es mío):

También existe un valor similar, nulo, cuyo significado es 'este valor está definido, pero no tiene valor'. La diferencia de significado entre indefinido y nulo es mayoritariamente académica y, por lo general, no es muy interesante. En los programas prácticos, a menudo es necesario comprobar si algo "tiene valor". En estos casos se puede utilizar la expresión algo == undefinido, porque, aunque no sean exactamente el mismo valor, null == undefinido producirá verdadero.

Entonces, supongo que la mejor manera de comprobar si algo no está definido sería:

if (something == undefined)

Las propiedades del objeto deberían funcionar de la misma manera.

var person = {
    name: "John",
    age: 28,
    sex: "male"
};

alert(person.name); // "John"
alert(person.fakeVariable); // undefined
Pandincus avatar Aug 26 '2008 07:08 Pandincus

¿Qué significa esto: "propiedad de objeto indefinida" ?

¡En realidad puede significar dos cosas muy diferentes! Primero, puede significar la propiedad que nunca se ha definido en el objeto y, segundo, puede significar la propiedad que tiene un valor indefinido . Veamos este código:

var o = { a: undefined }

¿ Es o.aindefinido? ¡Sí! Su valor no está definido. ¿ Es o.bindefinido? ¡Seguro! ¡No existe ninguna propiedad 'b' en absoluto! Bien, veamos ahora cómo se comportan los diferentes enfoques en ambas situaciones:

typeof o.a == 'undefined' // true
typeof o.b == 'undefined' // true
o.a === undefined // true
o.b === undefined // true
'a' in o // true
'b' in o // false

Podemos ver claramente que typeof obj.prop == 'undefined'y obj.prop === undefinedson equivalentes, y no distinguen esas diferentes situaciones. Y 'prop' in objpuede detectar la situación cuando una propiedad no se ha definido en absoluto y no presta atención al valor de la propiedad que puede no estar definido.

¿Entonces lo que hay que hacer?

1) Quiere saber si una propiedad no está definida por el primer o segundo significado (la situación más típica).

obj.prop === undefined // IMHO, see "final fight" below

2) Solo desea saber si el objeto tiene alguna propiedad y no le importa su valor.

'prop' in obj

Notas:

  • No se puede comprobar un objeto y su propiedad al mismo tiempo. Por ejemplo, esto x.a === undefinedo esto typeof x.a == 'undefined'aumenta ReferenceError: x is not definedsi x no está definido.
  • La variable undefinedes una variable global (por lo que en realidad lo es window.undefineden los navegadores). Ha sido compatible desde ECMAScript 1.ª edición y desde ECMAScript 5 es de sólo lectura . Entonces, en los navegadores modernos no se puede redefinir como verdadero , como a muchos autores les encanta asustarnos, pero esto sigue siendo cierto para los navegadores más antiguos.

pelea final: obj.prop === undefinedvstypeof obj.prop == 'undefined'

Ventajas de obj.prop === undefined:

  • Es un poco más corto y se ve un poco más bonito.
  • El motor JavaScript te dará un error si has escrito malundefined

Desventajas de obj.prop === undefined:

  • undefinedse puede anular en navegadores antiguos

Ventajas de typeof obj.prop == 'undefined':

  • ¡Es realmente universal! Funciona en navegadores nuevos y antiguos.

Desventajas de typeof obj.prop == 'undefined':

  • 'undefned'( mal escrito ) aquí es solo una constante de cadena, por lo que el motor de JavaScript no puede ayudarlo si lo ha escrito mal como lo acabo de hacer yo.

Actualización (para JavaScript del lado del servidor):

Node.js admite la variable global undefinedas global.undefined(también se puede usar sin el prefijo 'global'). No conozco otras implementaciones de JavaScript del lado del servidor.

Konstantin Smolyanin avatar Aug 08 '2013 20:08 Konstantin Smolyanin

La cuestión se reduce a tres casos:

  1. El objeto tiene la propiedad y su valor no undefined.
  2. El objeto tiene la propiedad y su valor es undefined.
  3. El objeto no tiene la propiedad.

Esto nos dice algo que considero importante:

Existe una diferencia entre un miembro indefinido y un miembro definido con un valor indefinido.

Pero lamentablemente typeof obj.foono nos dice cuál de los tres casos tenemos. Sin embargo podemos combinar esto "foo" in objpara distinguir los casos.

                               |  typeof obj.x === 'undefined' | !("x" in obj)
1.                     { x:1 } |  false                        | false
2.    { x : (function(){})() } |  true                         | false
3.                          {} |  true                         | true

Vale la pena señalar que estas pruebas nulltambién son las mismas para las entradas.

                               |  typeof obj.x === 'undefined' | !("x" in obj)
                    { x:null } |  false                        | false

Yo diría que en algunos casos tiene más sentido (y es más claro) verificar si la propiedad está ahí que verificar si no está definida, y el único caso en el que esta verificación será diferente es el caso 2, el raro caso de una entrada real en el objeto con un valor indefinido.

Por ejemplo: acabo de refactorizar un montón de código que tenía varias comprobaciones para determinar si un objeto tenía una propiedad determinada.

if( typeof blob.x != 'undefined' ) {  fn(blob.x); }

Lo cual fue más claro cuando se escribió sin un cheque por indefinido.

if( "x" in blob ) { fn(blob.x); }

Pero como ya se ha mencionado, estos no son exactamente iguales (pero son más que suficientes para mis necesidades).

Michael Anderson avatar Jun 08 '2011 04:06 Michael Anderson