2011-12-16 22 views
20

Me parece que hay cuatro formas diferentes que pueden determinar si un objeto dado (por ejemplo foo) tiene una propiedad determinada (por ejemplo bar) definidos:JavaScript: ¿Está definido un miembro?

  1. if (foo.hasOwnProperty(bar)) {
  2. if ('bar' in foo) {
  3. if (typeof foo.bar !== 'undefined') {
  4. if (foo.bar === undefined) {

Para determinar si hay una adecuada ty llamado "bar" en el objeto foo, ¿son equivalentes las tres afirmaciones? ¿Hay alguna semántica sublime que no sé que hace que estas tres afirmaciones sean diferentes?

+1

a tener en cuenta que, a menos que alguien ha sobrescrito la variable 'undefined' mundial, 3 también se puede hacer como si' (foo.bar == indefinido) {'. – Domenic

Respuesta

17

No, son totalmente diferentes. Ejemplo:

foo = {bar: undefined}; 
Object.prototype.baz = undefined; 
Object.prototype.bing = "hello"; 

continuación:

(typeof foo.bar != "undefined") === false 
('bar' in foo)     === true 
(foo.hasOwnProperty('bar'))  === true 


(typeof foo.baz != "undefined") === false 
('baz' in foo)     === true 
(foo.hasOwnProperty('baz'))  === false 


(typeof foo.bing != "undefined") === true 
('bing' in foo)     === true 
(foo.hasOwnProperty('bing'))  === false 

lógica-racional:

  • foo.hasOwnProperty('bar') implica 'bar' in foo
  • typeof foo.bar != "undefined" implica 'bar' in foo
  • Pero esas son las únicas inferencias se pueden dibujar; ninguna otra implicación es universalmente cierta, como lo muestran los contraejemplos anteriores.
+1

+1 - Me olvidé de considerar la barra como foo, pero configurada como indefinida –

2

una diferencia es que, el método 1 comprobará solo el objeto foo para la barra de propiedades, mientras que los dos últimos métodos también verificarán el prototipo de propiedad heredada.

2
'bar' in foo 

mirarán a cualquier parte de la cadena del prototipo. Las pruebas para ver si foo.bar! == undefined también devolverá verdadero si bar es en cualquier parte foo 's cadena de prototipo, pero recuerda que si la barra se define en foo, y conjunto de indefinido, esto devolverá falso.

hasOwnProperty es más quisquilloso - solo devolverá verdadero es bar se define como una propiedad directa de foo.

Per MDN

Cada objeto descendiente de objeto hereda el método hasOwnProperty. Este método se puede usar para determinar si un objeto tiene la propiedad especificada como propiedad directa de ese objeto; a diferencia del operador , este método no comprueba la cadena del prototipo del objeto.

10

Estos son todos diferentes:

  1. foo.hasOwnProperty('bar') le indica si foo tiene la propiedad y no realiza operaciones de búsqueda a lo largo de la cadena de prototipo.

  2. 'bar' in foo comprueba la cadena del prototipo y devuelve verdadero cuando encuentra la propiedad bar en cualquier objeto a lo largo de la cadena.

  3. typeof foo.bar != 'undefined' devuelve verdadero si foo o cualquier objeto a lo largo de su cadena de prototipo tiene la propiedad bar y su valor no es undefined.

Aquí es un ejemplo que demuestra que estas diferencias:

var foo1 = { 'bar1': 10, 'bar2': undefined }; 
function ctor() {} 
ctor.prototype = foo1; 
var foo2 = new ctor(); 
foo2.bar3 = 20; 

console.log(foo2.hasOwnProperty('bar1')); // false 
console.log(foo2.hasOwnProperty('bar2')); // false 
console.log(foo2.hasOwnProperty('bar3')); // true 
console.log(foo2.hasOwnProperty('bar4')); // false 

console.log('bar1' in foo2); // true 
console.log('bar2' in foo2); // true 
console.log('bar3' in foo2); // true 
console.log('bar4' in foo2); // false 

console.log(typeof foo2.bar1 != 'undefined'); // true 
console.log(typeof foo2.bar2 != 'undefined'); // false 
console.log(typeof foo2.bar3 != 'undefined'); // true 
console.log(typeof foo2.bar4 != 'undefined'); // false 
2

De hecho, existen algunas diferencias sutiles entre los diferentes métodos/palabras clave.

  1. foo.hasOwnProperty('bar') devuelve true sólo si la propiedad 'barra' se define en el propio objeto foo. Sin embargo, otras propiedades, como 'toString' devolverán false ya que se definen a partir de la cadena de prototipos.

  2. El operador de palabra clave in devuelve verdadero si la propiedad especificada está en el objeto especificado. Tanto 'bar' in foo como 'toString' in foo devolverían verdadero.

  3. Como está comprobando el estado de la propiedad, el resultado será verdadero cuando la barra no está definida en foo y cuando se define la barra pero el valor se establece en undefined.

0

que añadir a lo que han dicho otros, si lo que desea saber si existe una propiedad y tiene un valor distinto de Falsey- (no undefined, null, false, 0, "", NaN, etc ...), sólo puede hacer esto:

if (foo.bar) { 
    // code here 
} 

mientras los valores Falsey no son interesantes a usted para su circunstancia particular, este acceso directo le dirá si la variable se ha establecido en algo útil para usted o no.

Si desea saber si existe la propiedad en el objeto en cualquier forma, creo que este el más útil, breve y fácil de leer:

if ('bar' in foo) { 
    // code here 
} 

También se puede usar algo similar en los argumentos de funciones (de nuevo como Hasta que un valor Falsey- no es algo que te importa):

function foo(bar) { 
    if (bar) { 
     // bar was passed and has some non-falsey value 
    } 
}