33

So I have a simple Javascript class

class MyClass {
    constructor(x) {
        this.x = x === undefined ? 0 : x;
    }

    get x() {
        return this.x;
    }
}

When a MyClass is created, I want it's x to be set to the value passed in as a parameter. After this, I do not want it to be able to be changed, so I have intentionally not made a set x() method.

However, I guess I must be missing something fundamental, as this is giving me the "Cannot set property ... which only has getter" error.

How do I assign a value to x without creating a setter method?

4
  • You can't. A property must either be a plain property or else a getter/setter property. (I think; checking the spec) Commented Feb 6, 2019 at 21:29
  • Also your code as written will fail, because the reference to this.x in the getter will be understood as a function call to the getter, meaning infinite recursion. Commented Feb 6, 2019 at 21:32
  • Why would you want to do that? The main purpose for getter and setter is for read only or write only respectively or both. Without setter, one is saying that x will be read only and now assigning a value to it in constructor will obviously error. May be you are looking for something like readonly to be set once in the constructor only. Commented Jul 25, 2024 at 19:07
  • You can assign to x only once by this set(x) { if (this.x === undefined ) { this.x = x; } } and in the constructor only this.x = x; should suffice. Commented Jul 26, 2024 at 17:34

4 Answers 4

40

There are a couple problems here.

When you make a getter via get x() you are causing this.x to result in calling the getter, which will recurse indefinitely due to your get x() doing this.x.

Replace your references to this.x with this._x in this code like this:

class MyClass {
    constructor(x) {
        this._x = x === undefined ? 0 : x;
    }

    get x() {
        return this._x;
    }
}

Now your encapsulated x which is now _x will not be confused for a call to the getter via this.x.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you! This is exactly what I needed!
5

If you want an instance property to be read-only, then make it not writable:

class MyClass {
    constructor(x) {
        Object.defineProperty(this, "x", { value: x || 0 });
    }
}

A property can either be a "simple" property, as all properties were in the days of yore, or a getter/setter property.

When a property is a getter/setter property, all references to the property go through the getter or setter, including from within the getter and setter functions. Thus to store the property you need to use an alternative property name or (better) a Symbol instance.

Comments

4

If you want to create an immutable property a within your class definition, this os one way to do so with the method JavaScript gives is to do this (using Object.defineProperty()).

class MyClass {
  constructor(x) {
    Object.defineProperty(this, 'a', {
      enumerable: false,
      configurable: false,
      writable: false,
      value: x || 'empty'
    });
  }

}
let o = new MyClass('Hello');

console.log(o.a);
o.a = 'Will not change';
console.log(o.a);

Comments

0
class MyClass 
{
    constructor(x) {
        this.x = x === undefined ? 0 : x;
    }

    get() {
        return this.x;
    } 

    set(x) { return this.x = x;}
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.