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

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.