99 votes

Comment surcharger l'opérateur [] en javascript ?

Je n'arrive pas à trouver le moyen de surcharger l'opérateur [] en javascript. Quelqu'un le sait ?

Je pensais à quelque chose comme...

MyClass.operator.lookup(index)
{
     return myArray[index];
}

ou je ne regarde pas les bonnes choses.

3 votes

Les réponses ici sont fausses, les tableaux en JS sont juste des objets dont les clés sont coercibles avec des valeurs uint32 ( - 1) et ont des méthodes supplémentaires sur leur prototype.

0 votes

Faites juste votre MyClass un tableau. Vous pouvez copier les clés et les valeurs de myArray à votre var myObj = new MyClass() objet.

0 votes

J'aimerais surcharger l'opérateur {}, une idée ?

96voto

Kasztan Points 169

Vous pouvez le faire avec ES6 Proxy (disponible dans Chrome, Firefox) :

var p = Proxy.create({
  get: function(proxy, name) {
    return 'Hello, '+ name;
  }
});

document.write(p["World"]); // should print 'Hello, World'

Vérifiez les détails dans ce tutoriel .

3 votes

Comment l'utiliser pour créer notre propre classe avec un accesseur d'index ? Par exemple, je veux utiliser mon propre constructeur, je ne veux pas construire un Proxy.

1 votes

Ce n'est pas une véritable surcharge. Au lieu d'appeler des méthodes sur l'objet lui-même, vous appelez maintenant des méthodes du proxy.

0 votes

@Pacerier vous pouvez revenir target[name] dans le getter, OP ne fait que montrer les exemples

83voto

Peter Bailey Points 62125

Vous ne pouvez pas surcharger les opérateurs en JavaScript.

C'était proposé pour l'ECMAScript 4 mais rejeté.

Je ne pense pas que vous le verrez de sitôt.

6 votes

Cela peut être fait avec des proxies dans certains navigateurs déjà, et viendra à tous les navigateurs à un moment donné. Voir github.com/DavidBruant/ProxyArray

0 votes

Alors, comment se fait-il que jQuery renvoie des choses différentes selon que vous utilisez [] ou .eq() ? stackoverflow.com/a/6993901/829305

2 votes

Vous pouvez le faire maintenant avec un Proxy.

14voto

Brandon McKinney Points 742

La réponse simple est que JavaScript permet d'accéder aux enfants d'un objet via les crochets.

Donc vous pourriez définir votre classe :

MyClass = function(){
    // Set some defaults that belong to the class via dot syntax or array syntax.
    this.some_property = 'my value is a string';
    this['another_property'] = 'i am also a string';
    this[0] = 1;
};

Vous pourrez alors accéder aux membres de toutes les instances de votre classe avec l'une ou l'autre syntaxe.

foo = new MyClass();
foo.some_property;  // Returns 'my value is a string'
foo['some_property'];  // Returns 'my value is a string'
foo.another_property;  // Returns  'i am also a string'
foo['another_property'];  // Also returns 'i am also a string'
foo.0;  // Syntax Error
foo[0];  // Returns 1
foo['0'];  // Returns 1

2 votes

Je ne recommanderais certainement pas ceci pour des raisons de performance, mais c'est la seule solution réelle au problème ici. Peut-être qu'une modification indiquant que ce n'est pas possible ferait de cette réponse une excellente réponse.

7 votes

Ce site n'est pas ce que la question veut. La question demande un moyen d'attraper foo['random'] ce que votre code n'est pas capable de faire.

8voto

kstep Points 773

Comme l'opérateur de parenthèses est en fait un opérateur d'accès aux propriétés, vous pouvez l'utiliser avec des getters et des setters. Pour IE, vous devrez utiliser Object.defineProperty() à la place. Exemple :

var obj = {
    get attr() { alert("Getter called!"); return 1; },
    set attr(value) { alert("Setter called!"); return value; }
};

obj.attr = 123;

La même chose pour IE8+ :

Object.defineProperty("attr", {
    get: function() { alert("Getter called!"); return 1; },
    set: function(value) { alert("Setter called!"); return value; }
});

Pour IE5-7, il y a onpropertychange uniquement, ce qui fonctionne pour les éléments du DOM, mais pas pour les autres objets.

L'inconvénient de cette méthode est que vous ne pouvez accrocher que des requêtes à un ensemble prédéfini de propriétés, et non à une propriété arbitraire sans nom prédéfini.

0 votes

Pourriez-vous faire une démonstration de votre approche sur jsfiddle.net ? Je suppose que cette solution devrait fonctionner pour toute clé dans l'expression obj['any_key'] = 123; mais ce que je vois dans votre code, c'est que je dois définir un setter/getter pour toute clé (non encore connue). C'est impossible.

3 votes

Plus 1 pour compenser le moins 1 parce que ce n'est pas seulement IE.

0 votes

Cela pourrait-il être fait pour une fonction de classe ? J'ai du mal à trouver la syntaxe pour cela par moi-même.

4voto

XHR Points 679

Vous espérez donc faire quelque chose comme var whatever = MyClassInstance[4] ; ? Si c'est le cas, la réponse est simple : Javascript ne supporte pas actuellement la surcharge des opérateurs.

1 votes

Alors comment fonctionne jQuery. Vous pouvez appeler une méthode sur l'objet jQuery, comme $('.foo').html() ou récupérer le premier élément de domaine correspondant, comme $('.foo')[0].

2 votes

JQuery est une fonction, vous passez un paramètre à la fonction $. D'où les parenthèses () et non [].

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X