2011-07-08 29 views
12

me escribió el siguiente código a "estallar" una propiedad de un objeto como si se tratara de una matriz. Esto parece el tipo de código que me conseguiría golpeado por los programadores más graves, por lo que se preguntaba cuál es la forma correcta de hacer esto:Javascript "pop" de objeto

// wrong way to pop: 
for(key in profiles){ 
    var profile = profiles[key]; // get first property 
    profiles[key] = 0;   // Save over property just in case "delete" actually deletes the property contents instead of just removing it from the object 
    delete profiles[key];   // remove the property from the object 
    break;      // "break" because this is a loop 
} 

debería haber mencionado anteriormente, que a diferencia de un verdadero "pop" , No necesito que los objetos salgan en un orden particular. Solo necesito sacar uno y eliminarlo de su objeto principal.

+2

envolver el cuerpo en una 'si (profiles.hasOwnProperty (clave) {..', y quita el' = 0'' –

+4

¿Qué intenta hacer exactamente? Eliminar la primera propiedad que se agregó a un objeto? Esto no necesariamente funcionará, ya que no se garantiza el orden en que se recuperan las propiedades en un bucle 'for..in'. Aparte de eso usted debe utilizar 'hasOwnProperty' para asegurarse de que no es parte del prototipo, y no tiene que hacer nada que no sea' delete' a eliminar una propiedad de un objeto. –

Respuesta

13
for(key in profiles){ 

Usted realmente debe declarar key como var.

profiles[key] = 0;   // Save over property just in case "delete" actually deletes the property contents instead of just removing it from the object 

es innecesario. Eliminar no toca el valor de la propiedad (o en el caso de una propiedad que tiene un setter pero no getter, incluso requiere que tenga un valor).

Si el objeto tiene propiedades enumerables en su prototipo, entonces esto va a hacer algo extraño. Considere

Object.prototype.foo = 42; 

function pop(obj) { 
    for (var key in obj) { 
    // Uncomment below to fix prototype problem. 
    // if (!Object.hasOwnProperty.call(obj, key)) continue; 
    var result = obj[key]; 
    // If the property can't be deleted fail with an error. 
    if (!delete obj[key]) { throw new Error(); } 
    return result; 
    } 
} 

var o = {}; 
alert(pop(o)); // alerts 42 
alert(pop(o)); // still alerts 42 
2

No hay orden "correcta" a través de navegadores en lo que dan para un bucle for in. Algunos los hacen en el orden en que se colocan, otros lo hacen primero en índices numéricos. Así que realmente no hay manera de hacer esto sin crear su propio objeto personalizado

4

Propiedades de un objeto no se almacenan en una pila por lo que el concepto básico no va a funcionar de forma fiable (aparte de los otros temas mencionados en los comentarios anteriores).

Si realmente necesita una construcción tales intentar algo como esto.

var ObjectStack = function(obj) { 
    this.object = obj; 
    this.stack=[]; 
}; 
ObjectStack.prototype.push = function(key,value) { 
    this.object[key]=value; 
    this.stack.push(key); 
}; 
ObjectStack.prototype.pop = function() { 
    var key = this.stack.pop(); 
    var prop = this.object[key]; 
    delete this.object[key]; 
    return prop; 
}; 

var my_obj = {}; 
var my_stack = new ObjectStack(my_obj); 
my_stack.push("prop1",val1); 
my_stack.push("prop2",val2); 

var last_prop = my_stack.pop(); //val2 

Demostración: http://jsfiddle.net/a8Rf6/5/

+0

un problema con esta implementación es que estamos teniendo una pila, pero el inte rnal array es público. Cualquiera puede modificarlo de todos modos, o incluso reemplazarlo por otra cosa que no sea una matriz en absoluto. – yckart

+3

Javascript es fundamentalmente dinámico. Puedo cambiar 'Array.prototype.length' si elijo. Si bien es posible crear una implementación más compleja utilizando un cierre para ocultar la pila interna, este es un ejemplo de aprendizaje, y en la práctica es un código adicional para protegerte de una manera que el idioma nativo no lo hace de todos modos. –

1

Usted es capaz de crear el método pop como esto:.

Object.defineProperty(Object.prototype, 'pop',{ 
    writable: false 
    , configurable: false 
    , enumerable: false 
    , value: function (name) { 
     var value = this[name]; 
     delete this[name]; 
     return value; 
    } 
}); 

por alguna razón utilizando sólo Object.prototype.pop = función de jQuery ... rompe