Puis-je créer une méthode utilisable par chaque propriété d'un objet?
obj1 = new myClass(); obj1.a.raise(1); //a = 2 obj1.b.raise(3); //b = 5 obj1.c.raise(100); //c = 103
Ce que je veux, c'est pouvoir appeler la méthode rise sur n'importe quelle propriété d'objet via
XXX
Je veux donc pouvoir utiliser cette syntaxe: object.property.method ()
J'ai essayé de créer une relance sur le constructeur de classe, le prototype de classe ou l'objet prototype. Je n'ai pas non plus trouvé de mention à ce sujet ailleurs.
3 Réponses :
Il serait impossible pour obj.a
de renvoyer un numéro, tout en étant capable d'appeler obj.a.raise
pour le modifier.
Si vous sont ouverts à un petit ajustement, vous pouvez récupérer la valeur via une méthode appelée quelque chose comme .get
, tandis que la valeur sous-jacente est stockée et réaffectée dans la propriété _a
:
class myClass { constructor() { this._a = 1; this.a = { raise: num => this._a += num, get: () => this._a }; } } const obj = new myClass(); obj.a.raise(1); //a = 2 console.log(obj.a.get());
Je suis tout à fait certain que l'auteur voulait accéder à la variable comme obj.a
, pas obj.a.get ()
.
C'est à OP de le dire - mais sans quelque chose comme .get ()
, on ne pourra souvent pas utiliser le numéro sous-jacent sans le retirer d'abord de l'objet
Cela dépend du type d'objet. Dans un objet Number
, vous n'avez pas à choisir le numéro, vous pouvez faire quelque chose comme: (new Number (1)) + 1
qui vous donnera le primitive 2
.
Aussi, "Il serait impossible pour obj.a de renvoyer un nombre, tout en étant capable d'appeler obj.a.raise pour le modifier." est faux. Encore une fois, un objet Number
renvoie un nombre, mais vous pouvez également y mettre une fonction.
Vous devez toujours lancer un cast pour obtenir le numéro sous-jacent - vous ne pouvez pas faire un test comme this.a === 5
. Ce que vous avez avec Number
est un objet, pas un nombre
Eh bien, vous avez un point, mais vous pouvez simplement faire: this.a.valueOf () === 5
ou this.a == 5
si vous voulez comparer . Et si les objets Number
sont des objets, ils sont toujours (en quelque sorte) des nombres.
En utilisant ES6, vous pouvez le faire facilement. Vous n'avez peut-être pas besoin de solution complexe! Un exemple est donné ci-dessous.
2ème solution, pour utiliser la composition.
.as-console-row {color: blue!important}
class PriceList { constructor(price, amount) { this._price = price; this._amount = amount; } get price() { return this._price; } set price(p) { this._price += p; // validation could be checked here such as only allowing non numerical values } get amount() { return this._amount; } set amount(p) { this._amount += p; // validation could be checked here such as only allowing non numerical values } } const priceList = new PriceList(1, 10); console.log(priceList); // PriceList { _price: 1, _amount: 10 } priceList.amount = 10; priceList.price = 100; console.log(priceList); // PriceList { _price: 101, _amount: 20 } class Value { constructor(v) { this._val = v; } get val() { return this._val; } set(v) { this._val = v; } raise(m) { this._val += m; } } class PriceList2 { constructor(price, amount) { this.amount = new Value(amount); this.price = new Value(price); } } const priceList2 = new PriceList2(1, 10); console.log(priceList2); priceList2.amount.raise(10); priceList2.price.raise(100); console.log(priceList2.amount.val); // 20 console.log(priceList2.price.val); // 101 priceList2.amount.val = 1 priceList2.amount.raise(10); console.log(priceList2.amount.val); //30
Est-ce que trois classes entières sont nécessaires pour cela? Si tel est le cas, la solution est assez complexe.
@LearnforFun: J'ai laissé libre cours à comment faire. n'importe qui peut le simplifier. le refactoriser.
Pour littéralement toutes les réponses (sauf celle-ci), vous devez exécuter une fonction pour obtenir la valeur, ici c'est plus simplifié.
class myClass { constructor() { this.a = new Number(1); this.b = new Number(2); this.c = new Number(3); for (let p in this) { this[p].raise = x => { let fn = this[p].raise; this[p] = new Number(x + this[p]); this[p].raise = fn; } } } } let m = new myClass(); m.a.raise(15); m.a.raise(15); // A = 1 + 15 + 15 = 31 m.b.raise(10); m.b.raise(20); // B = 2 + 10 + 20 = 32 m.c.raise(17); m.c.raise(13); // C = 3 + 17 + 13 = 33 console.log(m.a + 1, m.b + 1, m.c + 1) // 32 33 34 // logging just m.a, m.b, m.c will get you an object with a raise function // only in stack overflow (or maybe other fake consoles), but the browser // console will definitely work and give you a Number object
Vous n'avez trouvé aucune mention de cela parce que cela ne fait pas partie de la langue. Vous pouvez passer le nom d'une propriété sous forme de chaîne, puis utiliser la notation
[]
pour accéder à une propriété.Presque toutes les réponses ici nécessitent que vous utilisiez une fonction
get ()
pour saisir la valeur ou faire quelque chose comme.val
. Pour chacun de ces cas,m.a, m.b et m.c
sont des objets. Cependant, il existe une manière de toujours obtenir un objet mais un objet JS Number. Voyez ma réponse.Merci pour toutes les suggestions. Mon objectif était de pouvoir définir 1 méthodes avec un comportement générique (comme augmenter la propriété appelante de x) et le faire fonctionner pour toutes les propriétés, de la même manière que la méthode hasOwnProperty () fonctionne sur n'importe quel objet ou propriété. Je pourrais donc économiser la mémoire d'avoir une fonction get pour chaque propriété. La méthode d'objet numérique créerait toujours une méthode pour chaque propriété ou?