将ES6类构造函数分配给' this'不重复变量名称

时间:2018-01-31 16:27:01

标签: javascript ecmascript-6 es6-class

当您编写ES6类时,可以在构造函数中使用解构,以便更容易使用默认选项:

class Person {
    constructor({
        name = "Johnny Cash",
        origin = "American",
        profession = "singer"
    } = {}) {
        this.name = name;
        this.origin = origin;
        this.profession = profession;
    }

    toString() {
        return `${this.name} is an ${this.origin} ${this.profession}`;
    }
}

这可以让你做到这样的事情:

const person = new Person();
console.log(person.toString());
// Returns 'Johnny Cash is an American singer'

const nina = new Person({
    name : "Nina Simone"
})
console.log(nina.toString());
// Returns 'Nina Simone is an American singer'

但是,您需要在构造函数中重复参数以将它们分配给类实例。我已经发现你可以做到这一点,以减少冗长:

Object.assign(this, { name, origin, profession });

但是你仍然需要重复这三个变量。有没有办法让分配更短而不重复变量?

3 个答案:

答案 0 :(得分:3)

您可以让构造函数接受一个“config”参数,然后说出Object.assign(this, config)。要拥有默认值,您只需设置默认对象,或将它们作为类属性分配给构造函数外部。

编辑致T.J.克劳德的观点,从技术上讲,使用Object.assign()时传入的任何内容都会被添加到您的对象中,这可能在很多方面都有害。我添加了一种方法来剥离配置对象,使其仅包含您定义的一组属性。 T.J.的解决方案也适用,我只是做了不同的选择,所以你有选择。

function stripObjToModel(model, obj) {
  // this method will modify obj
  Object.keys(obj).forEach(function (key) {
    if (!model.hasOwnProperty(key)) {
      delete obj[key];
    }
  });
  return obj;
}
class Person {
    constructor(config = {}) {
        var defaults = {
            name: "Johnny Cash",
            origin: "American",
            profession:  "singer"
        };
        Object.assign(this, defaults, stripObjToModel(defaults, config));
    }

    toString() {
        return `${this.name} is an ${this.origin} ${this.profession}`;
    }
}

const person = new Person();
console.log(person.toString());
// Returns 'Johnny Cash is an American singer'

const nina = new Person({
    name : "Nina Simone",
    foo: "bar",
    toString: function () {return "Hello World!";}
})
console.log(nina.toString());
// Returns 'Nina Simone is an American singer'

答案 1 :(得分:0)

可悲的是,我认为没有任何内置方法可以接受具有单独默认值的选项对象,并且只从您收到的对象中获取这些属性(而不是其他可能指定的外来属性)而不重复自己。这很不幸。 (这也不是我第一次想要解构对被解构对象的引用。)

这意味着我们必须自己出去,但这很简单:

function applyDefaults(target, options, defaults) {
    for (const key in defaults) { // Or `const key of Object.keys(defaults)` for just own props
        target[key] = (typeof options[key] === undefined ? defaults : options)[key];
    }
}

然后:

constructor(options = {}) {
    applyDefaults(this, options, {
        name: "Johnny Cash",
        origin: "American",
        profession: "singer"
    });
}

(如果在每个构造函数调用上重新创建对象让你担心,你可以将它移出课堂,但我不会担心它。)

但是然后在方法签名中没有描述单个属性的默认值,对我来说这是足够强大的理由继续并重复你现在拥有的名称。

答案 2 :(得分:0)

不是我提倡它,但你可以在技术上做到

constructor(options = {}) {
  ({
    name: this.name = "Johnny Cash",
    origin: this.origin = "American",
    profession: this.profession = "singer",
  } = options);
}

我个人认为你的示例代码有点重复看起来很好。