仅限getter的JavaScript ES6类

时间:2017-02-17 18:49:31

标签: javascript ecmascript-6 getter-setter getter es6-class

我想问一下,在ES6中如何才能在没有setter(readOnly)属性的情况下使用getter?为什么Webstorm告诉我这是一个错误?

这是我的代码:

class BasePunchStarter {

constructor(id,name,manufacturer,description,genres,targetPrice) {
    if (new.target==BasePunchStarter) {
        throw new TypeError("BasePunchStarter class cannot be instantiated directly!");
    }
    if (typeof id =="number") {
        // noinspection JSUnresolvedVariable
        this.id = id;
    } else throw new TypeError("ID must be a number!");
    if (typeof name=="string") {
        // noinspection JSUnresolvedVariable
        this.name = name;
    } else throw new TypeError("Name must be a string!");
    if(typeof manufacturer=="string") {
        // noinspection JSUnresolvedVariable
        this.manufacturer = manufacturer;
    } else throw new TypeError("Manufacturer must be a string!");
    if (typeof description=="string") {
        // noinspection JSUnresolvedVariable
        this.description = description;
    } else throw new TypeError("Description must be a string!");
    if(typeof genres=="Object") {
        // noinspection JSUnresolvedVariable
        this.genres=genres;
    } else new TypeError("Genres must be an Array of strings!");
    if (typeof targetPrice=="number") {
        // noinspection JSUnresolvedVariable
        this.targetPrice = targetPrice;
    } else new TypeError("Target price must be a number!");
    this.accumulatedMoney=0;
}
get accumulatedMoney() {
    return this._accumulatedMoney;
}
set accumulatedMoney(money) {
    this._accumulatedMoney=money;
}
get id() {
    return this._id;
}
get name() {
    return this._name;
}
get manufacturer() {
    return this._manufacturer;
}
get description() {
    return this._description;
}
get genres() {
    return this._genres;
}
get targetPrice() {
    return this._targetPrice;
}

我已放//noinspection JSUnresolvedVariable来取消警告。但是应该有比这更好的解决方案。

2 个答案:

答案 0 :(得分:5)

您似乎已将构造函数上的值分配给getter ,而不是前缀为下划线的支持字段。

constructor(id,name,manufacturer,description,genres,targetPrice){
    if(new.target==BasePunchStarter){
        throw new TypeError("BasePunchStarter class cannot be instantiated directly!");
    }
    if(typeof id =="number") {
        // use the backing field instead.
        this._id = id;
[..]

如果您还没有这样做,您应该在使用之前声明您的支持字段。

答案 1 :(得分:1)

你的代码不是惯用的JS。语言松散,其理念基于 duck typing 。你在构造函数中做的很糟糕,应该避免。 JavaScript不是Java。如果您想要强力和静态类型,请使用FlowTypeScript

getter和setter在ES6类中很容易使用,就像对象文字中的getter和setter一样。

如果您想要只读属性,则可以使用_编码约定并简单地避免使用setter。如果我们从文档中获取简单示例,我们会得到以下结果:



class Person {
  constructor(firstname, lastname) {
    this._firstname = firstname;
    this._lastname = lastname;
  }

  get firstname() {
    return this._firstname;
  }

  get lastname() {
    return this._lastname;
  }
}

let person = new Person('John', 'Doe');

console.log(person.firstname, person.lastname); // John Doe

// This is ignored
person.firstname = 'Foo';
person.lastname = 'Bar';

console.log(person.firstname, person.lastname); // John Doe




在JavaScript中,这个解决方案很好。但是,如果由于某种原因,你真的想要真正的封装,那就不是这样了。实际上,仍然可以直接访问带有_前缀的内部属性:



class Person {
  constructor(firstname, lastname) {
    this._firstname = firstname;
    this._lastname = lastname;
  }

  get firstname() {
    return this._firstname;
  }

  get lastname() {
    return this._lastname;
  }
}

let person = new Person('John', 'Doe');

console.log(person.firstname, person.lastname); // John Doe

// This is NOT ignored
person._firstname = 'Foo';
person._lastname = 'Bar';

console.log(person.firstname, person.lastname); // Foo Bar




完全封装的最佳解决方案包括使用IIFE在实例上创建本地范围和Object.freeze()以防止不必要的更改。

使用getter,它可以工作:



let Person = (() => {
  let firstname,
      lastname;

  class Person {
    constructor(first, last) {
      firstname = first;
      lastname = last;
    }

    get firstname() {
      return firstname;
    }

    get lastname() {
      return lastname;
    }
  }

  return Person;
})();

let person = new Person('John', 'Doe');
Object.freeze(person);

console.log(person.firstname, person.lastname); // John Doe

// This is ignored
person.firstname = 'Foo';
person.lastname = 'Bar';

console.log(person.firstname, person.lastname); // John Doe




没有吸气剂,它不起作用:



let Person = (() => {
  let firstname,
      lastname;

  class Person {
    constructor(first, last) {
      firstname = first;
      lastname = last;
    }
  }

  return Person;
})();

let person = new Person('John', 'Doe');
Object.freeze(person);

console.log(person.firstname, person.lastname); // undefined undefined

// This is ignored
person.firstname = 'Foo';
person.lastname = 'Bar';

console.log(person.firstname, person.lastname); // undefined undefined