joniba
joniba

Reputation: 3529

(javascript) invoke es6 getter using "call"

I'm trying to create a (class) instance that copies the behavior of another class, but using itself as the state context (this). Normal functions work fine (like the setValue function in the example below), but getters do not work. Here is a simple example:

const should = require('chai').should();

class One {
    setValue(val) {
        this._val = val;
    }

    get val() {
        return this._val;
    }
}

class Two {
    constructor(one) {
        this.one = one;
    }

    setValue(val) {
        this.one.setValue.call(this, val);
    }

    get val() {
        this.one.val.call(this);
    }
}

let one = new One();
let two = new Two(one);
one.setValue(1);
two.setValue(2);
one.val.should.equal(1);
two.val.should.equal(2);

The above code explodes on the last line with the error:

TypeError: this.one.val.call is not a function
    at Two.get val [as val] (C:\all\code\node-tests\invoke_getter.js:23:22)
    at Object.<anonymous> (C:\all\code\node-tests\invoke_getter.js:32:5)

How can I make something like this work?

Upvotes: 4

Views: 1716

Answers (1)

grodzi
grodzi

Reputation: 5703

Recall that property getters for class ends in its prototype

So to access the method, you may want to get it from its prototype:

const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(this.one), 'val')

Then you can call the getter on your two instance:

class One {
  setValue(val) {
    this._val = val
  }

  get val() {
    return this._val
  }
}

class Two {
  constructor(one) {
    this.one = one
  }

  setValue(val) {
    this.one.setValue.call(this, val)
  }

  get val () {
    const desc = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(this.one), 'val')
    return desc.get.call(this)
  }
}

const one = new One()
const two = new Two(one)
one.setValue(1)
console.log(two.val) // undefined (since _val does not exist on two yet)
two.setValue(2)
console.log(two.val) // 2
two._val = 3
console.log(two.val) // 3

Upvotes: 3

Related Questions