Last active
April 14, 2019 13:56
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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