I've been taken a bunch of JavaScript riddles lately and got really stuck on this one for like a day and a half (for context, all the others took 1 hour max). Since I want to come up with the final solution myself, I will post a somewhat similar piece of code just so I can grab the general idea and implement it as per the context of the riddle.
Assume this is the piece of code:
class Vehicle {
constructor(brand, model, power) {
this.brand = brand;
this.model = model;
this.power = power;
}
info() {
return `This vehicle is a ${this.brand} - ${this.model}, with a power of ${this.power}`;
}
}
//do something with my class here such that
//the next calls will return/display as follows
const v = new Vehicle('Mercedes', 'C class', 12345);
console.log(v.info()); // This vehicle is a Mercedes - C class, with a power of 12345
const {
info
} = v;
console.log(info()); // This vehicle is a Mercedes - C class, with a power of 12345
//To keep in mind, the function should stay the same, so a call to (info === v.info) should return true;
//And only the part of the code where it says to enter the code can be changed, so the class should be untouched.
I'm aware this shouldn't be a case where maybe it will be used in everyday life, as it is a riddle and just meant to challenge our brain, but it challenged me to the point I give up haha.
I tried looping over the entries of the Vehicle.prototype, and setting each one that is a function and is not the constructor to the same function bound to the class, or to the class.prototype or anything similar and it doesn't work.
How can I go about solving it, or at least make it so I can edit a function call for every time a new instance of that class is created?
Edit: I tried using the bind method, even tried something like this
Vehicle.prototype['info'] = Vehicle.prototype['info'].bind(Vehicle.prototype);
Vehicle.prototype['info'] = Vehicle.prototype['info'].bind(Vehicle);
Vehicle.prototype['info'] = Vehicle.prototype['info'].bind(Vehicle.prototype['info']);
I tried many alternatives and they didn't work since I have to have it bound to each instance of the class created. So if a new instance was created, and the same was done there, each one would return data according to the instance it was extracted from.
To keep info === v.info
as true
. You need to use bind()
.
class Vehicle {
constructor(brand, model, power) {
this.brand = brand;
this.model = model;
this.power = power;
}
info() {
return `This vehicle is a ${this.brand} - ${this.model}, with a power of ${this.power}`;
}
}
const v = new Vehicle('Mercedes', 'C class', 12345);
console.log(v.info());
const info = v.info;
console.log(info.bind(v)());
console.log(info === v.info);
Another elegant solution by gog. I added it here since this question is closed.
class Vehicle {
constructor(brand, model, power) {
this.brand = brand;
this.model = model;
this.power = power;
}
info() {
return `This vehicle is a ${this.brand} - ${this.model}, with a power of ${this.power}`;
}
}
let fn = Vehicle.prototype.info
Object.defineProperty(Vehicle.prototype, 'info', {
get() {
return this._bound ?? (this._bound = fn.bind(this))
}
});
const v = new Vehicle('Mercedes', 'C class', 12345);
console.log(v.info());
const {
info
} = v;
console.log(info());
console.log(info === v.info)