2008-12-22 14 views
35

Decir que tengo el siguiente código:JavaScript - Identificar si una propiedad se define y establece en 'indefinido', o indefinido

function One() {} 
One.prototype.x = undefined; 

function Two() {} 

var o = new One(); 
var t = new Two(); 

o.x y t.x será tanto evaluar a undefined. o.hasOwnProperty('x') y t.hasOwnProperty('x') ambos devolverán falso; lo mismo vale para propertyIsEnumerable. Dos preguntas:

  • ¿Hay alguna forma de saber si o.x está definido y configurado en undefined?
  • ¿Alguna vez hay alguna razón para hacerlo? (Si ambos ser semánticamente equivalentes?)

Una pequeña advertencia: haciendo (por propName en O) bucle producirá 'x' como una de las cuerdas, mientras que hacerlo en T no - así que hay una diferencia en la forma en que están representados internamente (al menos en Chrome).

Respuesta

61

Una forma un poco más simple que el método es utilizar la Javascript in operator

alert('x' in o); // true 
alert('x' in t); // false 
+2

¿La palabra clave 'in' está en un estándar ECMAScript? Está implementado en Gecko y Webkit, pero no sé si siempre se puede confiar en que esté presente. – kpozin

+1

@kpozin Puede usar 'in' de forma segura. Ver esta pregunta: http://stackoverflow.com/questions/2920765/javascript-in-operator-compatibility – chiborg

0

Una forma de hacerlo es la siguiente:

var definedProperties = []; 
for (var prop in o) definedProperties.push(prop); 

if (o.x === undefined && contains(prop, 'x')) { 
    //x is defined, but set to undefined 
} 

donde contains simplemente comprueba si cualquier elemento de la matriz es 'x'. ¿Es esta la única manera?

+1

"contiene"? Eso no es ECMAScript. Incluso si lo fuera, su solución es mucho más lenta y utiliza más recursos de los necesarios. Use "x en y" como dice en las otras respuestas. – some

+0

Lo sé, olvidé que ECMAScript tenía un operador 'in' = P. – Claudiu

0

Podría intentar poner un reloj en One.x, pero eso solo le indicaría en el momento en que se vuelva indefinido.

+0

No, él lo está definiendo con el valor primitivo 'indefinido'. – some

+0

Al definirlo se usaría "eliminar". – Tomalak

1

¿Algo como esto?

function isDefined(var){ 
    return (typeof(window[var]) == 'undefined') ? false : true; 
} 

o ..

function isDefined(var){ 
    return (window.var === undefined) ? false : true; 
} 
+0

estos actuarán de la misma manera para ambas variantes, creo que – Claudiu

1

No. No creo que una variable igual a undefined debe ser reconocido como "definido".

Ponerlo igual a undefined directamente es solo una forma perezosa de eliminarlo - como apposed a usar la palabra clave delete. Creo que esto solo significa que la recolección de basura no ha afectado la variable/propiedad.


[EDITAR]

En cuanto a su comentario sobre hasOwnProperty y propertyIsEnumerable, métodos para prototipos/propiedades no son ni propia del objeto ni numerable.

Object.prototype.foo = 'something'; 

var o = {bar: 'anything'}; 
o.hasOwnProperty('foo'); //=> false 
o.hasOwnProperty('bar'); //=> true 

Object.prototype.hasOwnProperty('foo'); //=> true 
+0

esto es posible. – Claudiu

+0

Ajustándolo al valor primitivo indefinido no elimine la propiedad, pero pierde la referencia a cualquier propiedad que contenga. No tiene nada que ver con la recolección de basura que no surtió efecto. – some

8

Object.hasOwnProperty (nombre) sólo devuelve cierto para los objetos que se encuentran en el mismo objeto, y falso para todo lo demás, incluyendo propiedades en el prototipo.

function x() { 
    this.another=undefined; 
}; 

x.prototype.something=1; 
x.prototype.nothing=undefined; 
y = new x; 

y.hasOwnProperty("something"); //false 
y.hasOwnProperty("nothing"); //false 
y.hasOwnProperty("another"); //true 

"someting" in y; //true 
"another" in y; //true 

Además, la única forma de eliminar una propiedad es usar eliminar. Poniéndolo en indefinido NO lo elimine.

La forma correcta de hacerlo es usar en como roborg dicho.

Actualización: indefinido es un valor primitivo, ver ECMAScript Language Specification la sección 4.3.2 y 4.3.9.

4

Ach, uno para el hilo anti-patrones allí.

undefined no es una palabra clave.

Cuando asigna escritura var foo = undefined; se está asignando el valor del símbolo undefined la que no se ha definido y por lo tanto el valor que obtendrá es "undefined". Produciría exactamente el mismo resultado si lo hubiera asignado UnDeFiNeD o NotFineAtAll o _qwertyuiop

¿Por qué es esto tan terrible? Bien aparte del hecho de que conduce a una comprensión falsa de lo que está sucediendo, ¿qué ocurre si carga una biblioteca o contrata a un desarrollador que escribe var undefined = true;

+1

ah, muy interesante. una nota, sin embargo, establecerlo en "UnDeFiNed" causará un error en tiempo de compilación, ya que esa variable no está definida. establecerlo en "Object.randomStringinserthereplease" actúa de la manera que usted dice que lo hará. – Claudiu

+1

quiere decir tiempo de ejecución, no hay tal cosa como compilar con JS, pero tiene razón, mi descripción asume el alcance. El problema surge porque undefined puede tratarse como una constante en muchas situaciones y ha sido admitido por algunos navegadores, pero * * no * es constante y no es seguro – annakata

+0

Si desea saber si algo no está definido independientemente de que alguien haya cambiado el valor de undefined: typeof x === "undefined" – some

Cuestiones relacionadas