TypeError: can't delete non-configurable array element

Message

TypeError: can't delete non-configurable array element (Firefox)
TypeError: Cannot delete property '2' of [object Array] (Chrome)

Type d'erreur

Quel est le problème ?

On a voulu raccourcir la longueur d'un tableau mais l'un des éléments de ce tableau est non-configurable. Lorsqu'on tronque un tableau, les éléments situés au-delà de la nouvelle longueur seront supprimés. Dans ce cas, c'est cette suppression qui n'a pas pu être effectuée.

L'attribut configurable permet de contrôler si la propriété peut être supprimée d'un objet et si ses attributs (en dehors de writable) peuvent être modifiés.

La plupart du temps, les propriétés d'un objet créé avec un littéral de tableau sont configurables. Toutefois, si on utilise Object.defineProperty() par exemple, la propriété n'est pas configurable par défaut.

Exemples

Propriétés non-configurables créées avec Object.defineProperty

Par défaut, la méthode Object.defineProperty() crée des propriétés non-configurables si on n'indique pas expressément le contraire :

js
var arr = [];
Object.defineProperty(arr, 0, { value: 0 });
Object.defineProperty(arr, 1, { value: "1" });

arr.length = 1;
// TypeError: can't delete non-configurable array element

Si on veut tronquer le tableau, il faut que les éléments excédants soient configurables :

js
var arr = [];
Object.defineProperty(arr, 0, { value: 0, configurable: true });
Object.defineProperty(arr, 1, { value: "1", configurable: true });

arr.length = 1;

Tableaux scellés (seal)

La méthode Object.seal() permet de marquer l'ensemble des propriétés (ici les éléments du tableau) comme non-configurables :

js
var arr = [1, 2, 3];
Object.seal(arr);

arr.length = 1;
// TypeError: can't delete non-configurable array element

Pour corriger l'erreur, il faut retirer l'appel à Object.seal() ou réaliser une copie du tableau. Dans ce dernier cas, on notera que tronquer la copie du tableau ne modifie pas la longueur du tableau original.

js
var arr = [1, 2, 3];
Object.seal(arr);

// On copie le tableau initial pour tronquer cette copie
var copie = Array.from(arr);
copie.length = 1;
// arr.length == 3

Voir aussi