David Ranieri
David Ranieri

Reputation: 41017

Getter and setter without members

Can we use getters and setters without defining a method for a member?

For example, transform this

class int {
    set value(val) {
        this._value = val | 0; // Truncate
    }
    get value() {
        return this._value;
    }
}

var x = new int();

x.value = 5 / 2;
console.log(x.value); // shows 2 instead of 2.5

to something like this:

class int {
    set (val) {
        this = val | 0; // Truncate
    }
    get () {
        return this;
    }
}

var x = new int();

x = 5 / 2;
console.log(x); // shows 2 instead of 2.5

Upvotes: 3

Views: 698

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1074666

There's no operation you can tap into for when the value of a variable (x in your case) is replaced with a new value. That's just not something JavaScript has. You can't do that even with a Proxy.

Your first definition of int is probably about as close as you're going to get.

People have tried various ways of getting primitive-like things like your int. None of them is really satisfactory. For instance, this is a not-uncommon attempt:

class Int {
    constructor(value) {
        Object.defineProperty(this, "value", {
            value: value | 0,
            enumerable: true
        });
    }
    set(value) {
        return new this.constructor[Symbol.species](value);
    }
    valueOf() {
        return this.value;
    }
    toString() {
        return this.value; // Even though it's not a string
    }
    static get [Symbol.species]() {
        return this;
    }
}

then:

let n = new Int(5);
console.log(`n = ${n}`); // n = 5
n = n.set(n / 2);
console.log(`n = ${n}`); // n = 2

but as soon as you do something that doesn't coerce to a primitive, like:

console.log(n);

you see the object-ness of it. You have to do:

console.log(+n);

which makes it a pretty big footgun, though the immutability helps with things like let m = n..

Example:

class Int {
    constructor(value) {
        Object.defineProperty(this, "value", {
            value: value | 0,
            enumerable: true
        });
    }
    set(value) {
        return new this.constructor[Symbol.species](value);
    }
    valueOf() {
        return this.value;
    }
    toString() {
        return this.value; // Even though it's not a string
    }
    static get [Symbol.species]() {
        return this;
    }
}

let n = new Int(5);
console.log(`n = ${n}`); // n = 5
n = n.set(n / 2);
console.log(`n = ${n}`); // n = 2

// But
console.log(n); // (object representation of it)

Upvotes: 3

Related Questions