Last active
September 4, 2021 17:01
-
-
Save chety/ef1924be2b970946b2a53eaebec8f963 to your computer and use it in GitHub Desktop.
Hashnode proxy article code samples(Part-1)
This file contains 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
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