web-dev-qa-db-fra.com

Javascript "pop" de l'objet

J'ai écrit le code suivant pour "extraire" une propriété d'un objet comme s'il s'agissait d'un tableau. Cela ressemble au genre de code qui me ferait gifler par des programmeurs plus sérieux, alors je me demandais quelle était la bonne façon de faire ceci:

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

J'aurais dû mentionner plus haut que, contrairement à un vrai "pop", je n'ai pas besoin que les objets apparaissent dans un ordre particulier. Je dois juste en extraire un et le supprimer de son objet parent.

14
Chris Dutrow
for( key in profiles ){

Vous devriez vraiment déclarer key en tant que var.

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

est inutile. La suppression ne touche pas la valeur de la propriété (ou dans le cas d'une propriété qui a un setter mais pas un getter, il faut même qu'elle ait une valeur).

Si l'objet a des propriétés énumérables sur son prototype, cela produira quelque chose d'étrange.

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
13
Mike Samuel

Les propriétés d'un objet ne sont pas stockées dans une pile. Le concept de base ne fonctionnera donc pas de manière fiable (à part les autres problèmes mentionnés dans les commentaires ci-dessus).

Si vous avez vraiment besoin d'une telle construction, essayez quelque chose comme ça.

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

Démo: http://jsfiddle.net/a8Rf6/5/

4
Jamie Treworgy

Il n'y a pas d'ordre "correct" entre les navigateurs dans ce qu'ils donnent pour une boucle for in. Certains les font dans l'ordre où ils sont placés, d'autres d'abord les index numériques. Donc, il n'y a vraiment aucun moyen de faire cela sans créer votre propre objet personnalisé

2
qwertymk

Vous pouvez créer la méthode pop comme ceci:.

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

pour une raison quelconque en utilisant uniquement Object.prototype.pop = function ... rompt JQuery

1
Mackraken

De nos jours, vous pouvez simplement utiliser l'opérateur spread avec sa méthode Rest:
const {clé, ... profilesWithoutKey} = profils;

Crédit à cet article de blog

1
Noam Gal

Une meilleure approche au lieu de modifier directement le tableau d’entrée. .

let arr = [{label: "a"}, {label: "b"}, {label: "p"}, {label: "c"}] 
let newArr = arr.filter(p => { return p.label !== "p";});
0
Devesh Chauhan