admin管理员组文章数量:1336568
I would like to ask, in ES6 how can I use getters only without setters (readOnly) properties? Why is Webstorm telling me that this is an error?
Here is my code:
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;
}
}
I had put //noinspection JSUnresolvedVariable
to suppress the warning. But there should be better solution than this.
I would like to ask, in ES6 how can I use getters only without setters (readOnly) properties? Why is Webstorm telling me that this is an error?
Here is my code:
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;
}
}
I had put //noinspection JSUnresolvedVariable
to suppress the warning. But there should be better solution than this.
-
1
If you're using ES6 classes, at the very least you can use
===
, too. Also, as a point of solid programming, making a constructor throw is a really bad plan. That's not the responsibility of a constructor. If you have type requirements, either make sure you're passing in already validated data (which you should do anyway), or use something like TypeScript so you get type safety baked in. – Mike 'Pomax' Kamermans Commented Feb 17, 2017 at 18:55 - 1 Off topic, but @Mike'Pomax'Kamermans, why shouldn't you make a constructor throw? That seems the safest, most natural way to signal errors (which may or may not be the fault of the caller). – A. L. Flanagan Commented Feb 17, 2017 at 19:31
-
Possibly unrelated error: in
if(typeof genres=="Object"){
, it should be"object"
, lowercase. – A. L. Flanagan Commented Feb 17, 2017 at 19:34 - 1 @A.L.Flanagan things like stackoverflow./a/77797/740553 explain it better than I can in a ment. – Mike 'Pomax' Kamermans Commented Feb 17, 2017 at 22:01
- 1 Thanks @Mike'Pomax'Kamermans, that actually makes a lot of sense. – A. L. Flanagan Commented Mar 10, 2017 at 19:10
2 Answers
Reset to default 6It seems that you're assigning the values on the constructor to the getters instead of the backing fields prefixed with underscore.
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;
[..]
In case you're not doing it already, you should declare your backing fields before using them.
Your code is not idiomatic JS. The language is loosely typed and its philosophy is based on duck typing. What you do in your constructor is awful and should be avoided. JavaScript is not Java. If you want strong and static typing, use Flow or TypeScript.
Getters and setters are easy to use in ES6 classes, just like getters and setters in object literals.
If you want read-only properties, you can use the _
coding convention and simply avoid setters. If we take the simple example from the documentation, we have the following result:
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
In JavaScript, this solution is just fine. But if, for some reason, you really want true encapsulation, this is not the way to go. Indeed, internal properties with the _
prefix can still be accessed directly:
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
The best solution for full encapsulation consists in using an IIFE to create a local scope and Object.freeze()
on instances to prevent unwanted changes.
With getters, it works:
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
Without getters, it does not work:
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
本文标签: ecmascript 6JavaScript ES6 class with getters onlyStack Overflow
版权声明:本文标题:ecmascript 6 - JavaScript ES6 class with getters only - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742403591a2468369.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论