Установка класса Javascript для каждого атрибута

Я пытаюсь создать класс, который имеет ряд объектов, назначенных в качестве атрибутов. Я застрял на реализации сеттеров на этих атрибутах.

Неудачный пример ниже. Когда я делаю record1.foo = 'bar'; // record.foo is now a string Я перезаписываю атрибут строкой, а не устанавливаю значение внутри класса Element.

Надеюсь, что это имеет смысл, я бы хотел, чтобы установщик записал значение в элемент, а не заменил его.

'use strict';

const assert = require('chai').assert;

class Element {

  constructor(name) {
    this.name = name;
    this.value = null;
  }

  getValue() {
    return this.value;
  }

  setValue(value) {
    this.value = value;
  }

  getName() {
    return this.name;
  }

  toString() {
    return this.getValue();
  }

}

class Record {

  constructor() {
    this.fields = ['name', 'age', 'foo'];
    this.fields.forEach((field) => {
      this[field] = new Element(field);
    });
  }

  setValue(field, value) {
    this[field].setValue(value);
  }

  getValue(field) {
    return this[field].getValue();
  }

}

let record1 = new Record();
record1.name.setValue('Bob');
record1.setValue('age', 42);

assert.equal(record1.getValue('name'), 'Bob');
assert.equal(record1.age, 42);

console.log('so far so good');

record1.foo = 'bar'; // record.foo is now a string
assert.equal(record1.getValue('foo'), bar);

2 ответа

Решение

Как динамичный способ сделать это так, как вы хотите, попробуйте это:

'use strict';

class Element {

  constructor(name) {
    this.name = name;
    this.value = null;
  }

  getValue() {
    return this.value;
  }

  setValue(value) {
    this.value = value;
  }

  getName() {
    return this.name;
  }

  toString() {
    return this.getValue();
  }

}

class Record {

  constructor() {
    this.fields = ['name', 'age', 'foo'];
    this.fields.forEach((field) => {
      let element = new Element(field);
      Object.defineProperty(this, field, {
        set: function(value) {
          element.setValue(value);
        },
        get: function() {
          return element;
        }
      });
    });
  }

  setValue(field, value) {
    this[field].setValue(value);
  }

  getValue(field) {
    return this[field].getValue();
  }

}

let record1 = new Record();
record1.name.setValue('Bob');
record1.setValue('age', 42);

console.log(record1.getValue('name') === 'Bob');
console.log(record1.age === 42);

record1.foo = 'bar';
console.log(record1.getValue('foo') === 'bar');

Насколько я могу сказать, это то, что вы хотите:

class Delegator {
  set foo (a) {
    this._foo.value = a;
  }

  get foo () {
    return this._foo.value;
  }

  constructor () {
    let fields = ['foo', 'value', 'name'];
    fields.forEach(fld => this[`_${fld}`] = new Element(fld));
  }
}

let instance = new Delegator();
instance.foo; // returns Element's value of foo
instance.foo = 'bar'; // sets Element's value to bar
Другие вопросы по тегам