Skip to content

Instantly share code, notes, and snippets.

@chety
Last active September 4, 2021 17:01
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 chety/ef1924be2b970946b2a53eaebec8f963 to your computer and use it in GitHub Desktop.
Save chety/ef1924be2b970946b2a53eaebec8f963 to your computer and use it in GitHub Desktop.
Hashnode proxy article code samples(Part-1)
let numbers = [1,2,3,4,5];
//First parameter in proxy constructor is target object which we want to wrap it
//second parameter is known as trappers which is basically a configuration object
numbers = new Proxy(numbers,{
//if there is no element, instead of undefined return a meaningfull message
//receiver points to this object. In this case it is numbers proxy object
get(target,property,receiver){
return target[property] ?? "No element exists"
},
//we want to prevent adding elements which are not numbers
//With typescript it is easy, but with javascript we achieve same result via set trapper
//Behind the scenes proxy calls corresponding internal methods. For set trapper internal
//method is [[Set]]. We do not have to write other setters for push,unshift ..etc. They
//all use internal [[Set]]
set(target,property,value,receiver){
const valueType = typeof(value);
if(valueType !== "number"){
console.error(`Expected number type value but got ${valueType}`)
return false;
}
target[property] = value;
return true;
}
})
console.log(numbers[123]); //returns "No element exists" instead of undefined
numbers.push(false); //throw an error
console.log(numbers)
function customFetch(url){
//...code to simulate fetching data from yrl
//...
console.log(`Got data from ${url} endpoint`)
}
customFetch = new Proxy(customFetch, {
apply(target,thisArg,params){
console.log("customFetch called with: ",params);
}
});
//output will be customFetch called with: (4) ['http://localhost:3000', 12, false, 'Chety']
//instead of "Got data from ....".
customFetch("http://localhost:3000",12,false,"Chety");
//AS you see we INTERCEPT!! function and execute another code block.
//Proxy lets us create powerfull wrappers.
function delay(fn,ms){
return new Proxy(fn,{
apply(target,thisArg,params){
//setTimeout(() => target.apply(thisArg,params),ms);
//If we do not use `this` object directly in our function we can use this
//instead of above one which creates an extra function wrapper
setTimeout(target,ms,...params)
}
})
}
let sayHello = (name) => console.log(`Hello there ${name}`);
sayHello = delay(sayHello,3000);
//proxy keeps all the properties of original function. Instead of returning a Proxy,
//if we return a wrapper function we will lose all the properties of the original function
console.log(sayHello.length,sayHello.name) // 1 sayHello.
sayHello("Rodin"); //Hello there Rodin(AFter 3 seconds)
//Let's say we assume a property which starts with '_' is private property of an object.
//Nobody should access(get),write(set),enumurate(ownKeys) and delete(deleteProperty) it.
//We can achieve such a behaviour with Proxy
let user = {
name: "John",
age: 33,
_password: "secret"
};
user = new Proxy(user, {
get(target,prop,receiver){
if(prop.startsWith("_")){
throw new Error("Can not access private values")
}
return target[prop]
},
set(target,prop,value,receiver){
if(prop.startsWith("_")){
return false
}
target[prop] = value;
return true
},
ownKeys(target){
return Object.keys(target).filter(prop => !prop.startsWith("_"))
},
deleteProperty(target,prop){
if(prop.startsWith("_")){
return false
}
delete target[prop];
return true
}
})
Object.keys(user).forEach(key => console.log(key)) //name,age
for(const key in user){
console.log(`${key} = ${user[key]}`); // name = John, age = 33
}
//console.log(user._password); //Uncaught Error: Can not access private values
user._password = "qwerty"; // won't set the property
delete user._password; //won't delete the property
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment