每个属性上的Javascript类设置器

时间:2018-04-06 15:43:56

标签: javascript node.js metaprogramming

我正在尝试创建一个具有多个作为属性分配的对象的类。我坚持在这些属性上实现setter。

以下示例失败。当我record1.foo = 'bar'; // record.foo is now a string时,我用字符串覆盖属性,而不是在Element类中设置值。

希望这是有道理的,我希望一个setter将值写入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 个答案:

答案 0 :(得分:1)

据我所知,这就是你想要的:

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

答案 1 :(得分:1)

作为一种动态的方式,您可以尝试这样做:

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