web-dev-qa-db-fra.com

Comment découper un objet en Javascript?

J'essayais de découper un objet à l'aide de Array.prototype, mais il renvoie un tableau vide. Existe-t-il une méthode pour découper des objets en plus des arguments de passage ou s'agit-il simplement d'un code erroné? THX!!

var my_object = {
 0: 'zero',
 1: 'one',
 2: 'two',
 3: 'three',
 4: 'four'
};

var sliced = Array.prototype.slice.call(my_object, 4);
console.log(sliced);
11
JC Garcia

J'essayais de découper un objet en utilisant Array.prototype, mais il renvoie un tableau vide

C'est parce qu'il n'a pas de propriété .length. Il essaiera d'y accéder, obtiendra undefined, le convertira en un nombre, obtiendra 0 et découpera au maximum autant de propriétés de l'objet. Pour obtenir le résultat souhaité, vous devez donc lui attribuer une variable length ou un itérateur manuellement à l'aide de l'objet:

var my_object = {0: 'zero', 1: 'one', 2: 'two', 3: 'three', 4: 'four'};

my_object.length = 5;
console.log(Array.prototype.slice.call(my_object, 4));

var sliced = [];
for (var i=0; i<4; i++)
    sliced[i] = my_object[i];
console.log(sliced);
8
Bergi

Personne n'a mentionné Object.entries () yet, ce qui pourrait être la manière la plus flexible de le faire. Cette méthode utilise le même ordre que for..in lors de l'énumération des propriétés, c'est-à-dire l'ordre dans lequel les propriétés ont été entrées à l'origine dans l'objet. Vous obtenez également des sous-tableaux avec à la fois une propriété et une valeur, vous pouvez donc utiliser ce que vous voulez ou les deux. Enfin, vous n'avez pas à vous soucier des propriétés numériques ou de la définition d'une propriété de longueur supplémentaire (comme vous le faites lorsque vous utilisez Array.prototype.slice.call()).
Voici un exemple:

const obj = {'prop1': 'foo', 'prop2': 'bar', 'prop3': 'baz', 'prop4': {'prop': 'buzz'}};

Vous voulez trancher les deux premières valeurs:

Object.entries(obj).slice(0,2).map(entry => entry[1]);
//["foo", "bar"]

Toutes les clés?

Object.entries(obj).slice(0).map(entry => entry[0]);
//["prop1", "prop2", "prop3", "prop4"]

La dernière paire clé-valeur?

Object.entries(obj).slice(-1)
//[ ['prop4', {'prop': 'buzz'}] ]
25
trad
var obj = {0: 'zero', 1: 'one', 2: 'two', 3: 'three', 4: 'four'};
var result = Object.keys(obj).slice(0,2).map(key => ({[key]:obj[key]}));

console.log(result);

[{'0': 'zero'}, {'1': 'one'}]

3
rekinyz

Vous pouvez reduce le résultat de la fonction Object.keys 

const myObject = {
 0: 'zero',
 1: 'one',
 2: 'two',
 3: 'three',
 4: 'four'
};

const sliced = Object.keys(myObject).slice(0, 2).reduce((result, key) => {
                    result[key] = myObject[key];

                    return result;
                }, {});

console.log(sliced);

2
Amerzilla

Je pense que cela peut vous aider:

var my_object = { 0: 'zero', 1: 'one', 2: 'two', 3: 'three', 4: 'four' };

var sliced = Object.keys(my_object).map(function(key) { return my_object[key] }).slice(4);

console.log(sliced);
1
Mikhail Lipilin

Essayez d’ajouter une propriété 'length' à my_object et votre code devrait alors fonctionner:

    var my_object = {
     0: 'zero',
     1: 'one',
     2: 'two',
     3: 'three',
     4: 'four',
     length: 5
    };
    
    var sliced = Array.prototype.slice.call(my_object, 4);
    console.log(sliced);

1
Ted Hopp

// Works, but acts weird when things get serious
// Avoids screwing with the properties of my_object
// You don't get Object.create() until ES5.1
function lazySlice(obj, idx) {
  var newObj = Object.create(obj, { length: {value: Object.keys(obj).length} }),
  idx = idx || 0;

  return Array.prototype.slice.call(newObj, idx);
}

// Only gives you own enumerable properties with keys "0" to n
// Preserves element order (based on key number)
// Ignores non-numbered keys
// You don't get Object.keys() until ES5
function enumSlice(obj, idx) {
  var arr = [], 
    keys = Object.keys(obj),
    idx = idx || 0;

  for (var i = 0; i <= keys.length - 1; i++)
    if (keys[i] >= idx && keys[i] % 1 === 0 && keys[i] >= 0 && keys[i].indexOf('e') < 0) 
      arr.Push(obj[keys[i]]);

  return arr;
}

var my_object = {
  0: 'zero',
  1: 'one',
  2: 'two',
  3: 'three',
  4: 'four'
}; 
console.log(lazySlice(my_object, 3));      // [ 'three', 'four' ]
console.log(enumSlice(my_object, 3));      // [ 'three', 'four' ]

var mixed_object = {
   "9": 'nine',
   "2": 'two',
   "1": 'one',
   "7": 'seven',
   "7.5": 'seven point five',
   "1e4": 'sneaky',
   "-4": 'negative four',
   "0": 'zero',
   "length": 35
};
console.log(lazySlice(mixed_object));      // [ 'zero', 'one', 'two', , , , , 'seven',  ]
console.log(enumSlice(mixed_object));      // [ 'zero', 'one', 'two', 'seven', 'nine' ]

0
Karim Temple

Vous ne pouvez pas sauf si il a un [Symbol.iterator] fonction générateur et La propriété length existe. Tel que;

var my_object = { 0: 'zero', 1: 'one', 2: 'two', 3: 'three', 4: 'four', length:5 },
       sliced;

my_object[Symbol.iterator] = function* (){
                                          var oks = Object.keys(this);
                                          for (var key of oks) yield this[key];
                                         };

sliced = Array.prototype.slice.call(my_object, 2);
console.log(sliced);

0
Redu

Vous n'en parlez pas dans votre question, mais cela ressemble terriblement à un objet arguments. 

Convertissez-le en un tableau en utilisant Array.from() puis utilisez-le comme n'importe quel autre tableau. Tant qu'il s'agit d'un objet énumérable.

Pour un polyfill pour les anciens navigateurs, voir https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from

0
jishi