Skip to content

Instantly share code, notes, and snippets.

@XoseLluis
Last active April 14, 2019 13:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save XoseLluis/0052f4b6b9eca90e503c2bd717d4e6e1 to your computer and use it in GitHub Desktop.
Save XoseLluis/0052f4b6b9eca90e503c2bd717d4e6e1 to your computer and use it in GitHub Desktop.
Create an immutable wrapper (that allows cloning and modification by means of set_XXX methods) around and existing object: https://deploytonenyures.blogspot.com/2019/04/immutability-via-proxies.html
function createImmutable(item){
let handler = {
set: function(target, property, value){
//do nothing, this object is no longer "directly" mutable
console.log("hey, I'm immutable, you can't set me like this");
},
//object is mutable only by invoking a "set_XXXX" method
//we trap that get and return a function that will create the new object with the mutated property
//and returns a proxy around the new object, so that immutability continues to work in ensuing assignments
get: function(target, property, receiver){
if (property.startsWith("set_")){
let propName = property.substring(4);
console.log("assigning to " + propName + " via proxy");
return function(value){
//either use the trapped target or "this"
//let newItem = new target.constructor();
let newItem = new this.constructor();
Object.assign(newItem, target);
//notice I've just doing shallow cloning
newItem[propName] = value;
return new Proxy(newItem, handler);
}
}
else{
return target[property];
}
}
};
return new Proxy(item, handler);
}
//Let's test it
class Person{
constructor(name){
this.name = name;
}
say(word){
return `${word}, I'm ${this.name}`;
}
}
//--- Main
console.log("started");
let p1 = new Person("Francois");
console.log("p1 says: " + p1.say("hi"));
let immutableP1 = createImmutable(p1);
console.log("immutableP1" + JSON.stringify(immutableP1));
immutableP1.name = "Xuan";
console.log("immutableP1" + JSON.stringify(immutableP1));
let immutableP2 = immutableP1.set_name("Xuan");
console.log("immutableP2" + JSON.stringify(immutableP2));
console.log(immutableP2.say("hi"));
let immutableP3 = immutableP2.set_name("Emmanuel");
console.log("immutableP3" + JSON.stringify(immutableP3));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment