2

Is it possible to change the class of a Javascript variable ?

Let's say I have 2 classes :

class A {
  constructor(x) {
    this.x = x;
  }
}

class B {
  constructor(x, y) {
     this.x = x;
     this.y = y;
  }
}

And one variable of type A

let a = new A(20);

How coulid I change the type of a such that

(a instanceof B)

return true and not false ?

EDIT : I would like to know to solve a specific problem. I have a tree structure where each node of the tree is a Javascript object of class A or B (actually I have more class which all inherit from a base class but let's keep it simple). At some point, I would like to transform a node A into a node B. But I only have access to the node itself, not the parent nodes. So I would like to make a method inside the class A which transform the instanciated variable into an object of class B.

2
  • Is this pure curiosity or a concrete problem you're trying to solve? (in which case, tell us more about it). Commented May 1, 2021 at 15:45
  • I am trying to solve a specific problem. I edited my question Commented May 1, 2021 at 15:57

2 Answers 2

3

Make one of the classes extend the other?

class B {
  constructor(x, y) {
     this.x = x;
     this.y = y;
  }
}
class A extends B {
  constructor(x) {
    super();
    this.x = x;
  }
}



let a = new A(20);
console.log(a instanceof B);

Or set the prototype manually and return an object from A (weird):

class B {
  constructor(x, y) {
     this.x = x;
     this.y = y;
  }
}
class A {
  constructor(x) {
    const instance = Object.create(B.prototype);
    instance.x = x;
    return instance;
  }
}



let a = new A(20);
console.log(a instanceof B);

Or do it outside (extremely weird, don't do this):

class B {
  constructor(x, y) {
     this.x = x;
     this.y = y;
  }
}
class A {
  constructor(x) {
    this.x = x;
  }
}



let a = new A(20);
Object.setPrototypeOf(a, B.prototype);
console.log(a instanceof B);

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

Comments

0

In response to your update, one possible solution would be to employ a Pointer object. A Pointer is a transparent proxy that redirects every "set" and "get" operation to its target. Additionally, it provides a special property ($$$ in this example) that allows to change the target without changing the pointer itself. This way, you can replace an object "in place", given only a direct reference to it.

For the rest of the application, Pointer(x) looks and behaves exactly like x.

Example:

let Pointer = target => new Proxy({}, {
    getPrototypeOf() {
        return Reflect.getPrototypeOf(target)
    },
    get(_, p) {
        return Reflect.get(target, p)
    },
    set(_, p, v) {
        if (p === '$$$')
            return target = v
        return Reflect.set(target, p, v)
    }
})

//

class A {
    hello() {
        return 'aaa'
    }
}

class B {
    hello() {
        return 'BBB'
    }
}

let objects = [
    Pointer(new A),
    Pointer(new A),
    Pointer(new A),
    Pointer(new A),
]

function setObjectToB(obj) {
    obj.$$$ = new B
}

console.log(...objects.map(x => x.hello()))
console.log(objects[2] instanceof A)

setObjectToB(objects[2])

console.log(...objects.map(x => x.hello()))
console.log(objects[2] instanceof B)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.