Skip to content

Instantly share code, notes, and snippets.

@shikelong
Created January 10, 2022 09:12
Show Gist options
  • Save shikelong/49e157d1f9936997a1e6ae52f8f06c57 to your computer and use it in GitHub Desktop.
Save shikelong/49e157d1f9936997a1e6ae52f8f06c57 to your computer and use it in GitHub Desktop.
ES6 Proxy Playground
function consoleSplit(description = '') {
console.log('-'.repeat(25) + description + '-'.repeat(25));
}
consoleSplit('Get, Set, Has, DeleteProperty')
const p1 = {
name: 'rio',
age: 20,
}
function sayHello(name) {
return 'Hello' + (name || '')
}
const p1Handler = {
get(target, prop) {
//hide age
if (prop === 'age') {
return 'Unknown';
} else if (prop === 'job') {
return 'Programmer';
}
// return target[prop];
return Reflect.get(target, prop);
},
set(target, prop, value) {
if (prop === 'job') {
return false;
} else if (prop === 'age') {
console.log('set age: ', value);
if (value > 100) {
throw new Error('too old');
} else if (value < 0) {
throw new Error('too young');
}
}
// target[prop] = value;
Reflect.set(target, prop, value);
},
has(target, prop) {
if (prop === 'job') {
return true;
}
// return prop in target;
return Reflect.has(target, prop);
},
deleteProperty(target, prop) {
if (prop in target) {
console.log('delete: ', prop);
return Reflect.deleteProperty(target, prop);
}
return false
}
}
const p1Proxy = new Proxy(p1, p1Handler);
//get trap
console.log('p1Proxy.age: ', p1Proxy.age);
//set trap
// p1Proxy.age = -1;
p1Proxy.age = 23;
//has trap
if ('job' in p1Proxy) {
p1Proxy.job = 'teacher';
console.log('p1Proxy.job: ', p1Proxy.job);
}
//delete trap
// delete p1Proxy.job;
// delete p1Proxy.age;
let deleteNameResult = delete p1Proxy.name;
console.log('p1Proxy: ', p1Proxy, deleteNameResult);
consoleSplit('Apply');
const fnHandler = {
apply(target, thisArg, argArray) {
//add param check via proxy
console.log('Apply trap: ', argArray);
if (argArray.length !== 1 || typeof argArray[0] !== 'string') {
throw new Error('arguments error');
}
return Reflect.apply(target, thisArg, argArray);
}
}
const fnProxy = new Proxy(sayHello, fnHandler);
fnProxy('rio');
// fnProxy('rio', 'james');
// fnProxy(21312);
consoleSplit('Constructor');
function Person(name, age) {
this.name = name;
this.age = age;
}
const ConstructorHandler = {
construct(target, argArray) {
if (argArray[0] === 'momo') {
argArray[0] = 'Mrs.momo';
}
return Reflect.construct(target, argArray);
}
}
const PersonProxy = new Proxy(Person, ConstructorHandler);
const p2 = new PersonProxy('momo', 1.2);
console.log('p2: ', p2);
consoleSplit('SetPrototypeOf, GetPrototypeOf');
//setPrototypeOf and getPrototypeOf trap
const p3 = {
name: 'kit',
age: 30,
}
const protoTypeHandler = {
setPrototypeOf(target, proto) {
console.log('setPrototypeOf: ', proto);
return Reflect.setPrototypeOf(target, proto);
},
getPrototypeOf(target) {
console.log('getPrototypeOf: ', target);
return Reflect.getPrototypeOf(target);
}
}
const p3Proxy = new Proxy(p3, protoTypeHandler);
console.log('p3 proto before set: ', p3Proxy.__proto__);
// Object.setPrototypeOf(p3Proxy, {a: 1});
p3Proxy.__proto__ = {a: 1};
console.log('p3 proto after set: ', Object.getPrototypeOf(p3Proxy));
consoleSplit("isExtensible, preventExtensions")
const canNotExtensible = new Proxy({name: 'odo'}, {
isExtensible(target) {
console.log('isExtensible: ', target);
return Reflect.isExtensible(target);
},
preventExtensions(target) {
console.log('preventExtensions: ', target);
return Reflect.preventExtensions(target);
}
})
Object.preventExtensions(canNotExtensible);
canNotExtensible.age = 12;
console.log('canNotExtensible: ', Object.isExtensible(canNotExtensible));
consoleSplit('ownKeys/getOwnPropertyDescriptor')
//https://stackoverflow.com/questions/65339985/why-isnt-ownkeys-proxy-trap-working-with-object-keys
const ownKeysHandler = new Proxy({name: 'odo', country: 'China'}, {
ownKeys(target) {
// const result = Reflect.ownKeys(target);
return ['a', 'b', Symbol('c')];
},
getOwnPropertyDescriptor(target, prop) {
return {
enumerable: true,
configurable: true,
writable: true,
}
}
})
for (const key in ownKeysHandler) {
console.log('for in keys: ', key);
}
console.log('Object.keys: ', Object.keys(ownKeysHandler));
console.log('Object.getOwnPropertyNames: ', Object.getOwnPropertyNames(ownKeysHandler));
console.log('Object.getOwnPropertySymbols: ', Object.getOwnPropertySymbols(ownKeysHandler));
consoleSplit("defineProperty")
var definePropertyHandler = new Proxy({name: 'roy'}, {
defineProperty(target, prop, descriptor) {
// console.log('defineProperty: ', descriptor);
return Reflect.defineProperty(target, prop, descriptor);
}
})
//this trap intercepts the defineProperty operator, include Object.defineProperty/Object.defineProperties.
definePropertyHandler = Object.defineProperty(definePropertyHandler, 'age', {
value: 29,
writable: true,
configurable: true,
enumerable: true
})
definePropertyHandler.gender = 'male';
console.log('definePropertyHandler: ', definePropertyHandler);
//output:
// -------------------------Get, Set, Has, DeleteProperty-------------------------
// p1Proxy.age: Unknown
// set age: 23
// p1Proxy.job: Programmer
// delete: name
// p1Proxy: { age: 23 } true
// -------------------------Apply-------------------------
// Apply trap: [ 'rio' ]
// -------------------------Constructor-------------------------
// p2: Person { name: 'Mrs.momo', age: 1.2 }
// -------------------------SetPrototypeOf, GetPrototypeOf-------------------------
// getPrototypeOf: { name: 'kit', age: 30 }
// p3 proto before set: {}
// setPrototypeOf: { a: 1 }
// getPrototypeOf: { name: 'kit', age: 30 }
// p3 proto after set: { a: 1 }
// -------------------------isExtensible, preventExtensions-------------------------
// preventExtensions: { name: 'odo' }
// isExtensible: { name: 'odo' }
// canNotExtensible: false
// -------------------------ownKeys/getOwnPropertyDescriptor-------------------------
// for in keys: a
// for in keys: b
// Object.keys: [ 'a', 'b' ]
// Object.getOwnPropertyNames: [ 'a', 'b' ]
// Object.getOwnPropertySymbols: [ Symbol(c) ]
// -------------------------defineProperty-------------------------
// definePropertyHandler: { name: 'roy', age: 29, gender: 'male' }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment