1
votes

Puis-je créer une méthode de classe utilisable par chaque propriété d'un objet créé?

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 commentaires

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?


3 Réponses :


-1
votes

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());


6 commentaires

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.



-1
votes

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


2 commentaires

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.



-1
votes

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


0 commentaires