Last active
February 14, 2024 01:53
-
-
Save dotproto/1e66288d5799b8e4b27be19bb44b9cf3 to your computer and use it in GitHub Desktop.
Some test code generated while trying to wrap my head around how JS proxies work and how I might leverage them
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
// Resources | |
// | |
// - http://exploringjs.com/es6/ch_proxies.html | |
// - https://github.com/tvcutsem/harmony-reflect/issues/41 | |
// - https://esdiscuss.org/topic/proxies-stratifying-tostring-valueof | |
// - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy | |
// - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toPrimitive | |
// - https://console.spec.whatwg.org/#inspection | |
// NOTE: When Chrome logs "Symbol(Symbol.toPrimitive)", that corisponds to | |
// a funciton on an object set to Symbol.toPrimitive. For example: | |
// | |
// ``` | |
// { [Symbol.toPrimitive]: () => null } | |
// ``` | |
{ | |
console.clear() | |
let TargetProto = { | |
'type': 'TargetProto', | |
toString: () => 'TargetProto.toString()', | |
valueOf: () => 'TargetProto.valueOf()', | |
} | |
let handler = { | |
get: (target, property, receiver) => { | |
console.debug('> handler.get()', property, typeof property) | |
if (!(property in target) && typeof property === 'string') { | |
console.debug(`> handler.get(): Proxying '${property}'`) | |
target[property] = new Dynamic() | |
} | |
return target[property] | |
}, | |
// Only used when the object being proxied is a function. Originally I was hoping | |
// it would be used when a property was called as a function. | |
apply: (target, thisArg, argumentsList) => { | |
console.debug('> handler.apply(): ', argumentsList.join(", ")) | |
return target.apply(thisArg, argumentsList) | |
}, | |
} | |
// Creates an object who's properties will be dynamically generated | |
function Dynamic() { | |
return new Proxy(Object.create(TargetProto), handler) | |
} | |
Dynamic.prototype.toString = function toString() { '> Dynamic.toString()' } | |
Dynamic.prototype.valueOf = function valueOf() { '> Dynamic.valueOf()' } | |
// ------------------------------------------------------------------------- | |
// NOTE: The following conventions are used to help distinguish log messages | |
// | |
// :: - Denotes the beginning of a new test case. Should be followed by a label | |
// > - Helps track the proxy call sequence that leads to the final result | |
// - Unprefixed log lines indicate what was returned by the lookup/function call | |
console.log(':: Create Dynamic instance') // :: Create Dynamic instance | |
var d = Dynamic() | |
// NOTE: We get an inspectable "Proxy {}" in our output because that's what | |
// console.log prints. Unfortunately we have no control over how console.log | |
// handles printing, as noted in the WHATWG spec: | |
// | |
// https://console.spec.whatwg.org/#inspection | |
console.log(':: console.log(foo.bar.baz)') // :: console.log(foo.bar.baz) | |
console.log(d.foo.bar.baz) // > handler.get() foo string | |
// > handler.get() bar string | |
// > handler.get() baz string | |
// Proxy {} | |
console.log(':: console.log(+d)') // :: console.log(+d) | |
console.log(+d) // > handler.get() Symbol(Symbol.toPrimitive) symbol | |
// > handler.get() valueOf string | |
// NaN | |
// | |
// NOTE: Unary plus attempts to convert the value returned | |
// by the `valueOf()` call ("TargetProto.valueOf()") | |
// into a number, thus final result of NaN. | |
console.log(':: console.log(d.toString())') // :: console.log(d.toString()) | |
console.log(d.toString()) // > handler.get() toString string | |
// TargetProto.toString() | |
console.log(':: console.log(d.valueOf())') // :: console.log(d.valueOf()) | |
console.log(d.valueOf()) // > handler.get() valueOf string | |
// TargetProto.valueOf() | |
/* | |
// Alerts are anoying. Only reason this is here is 'cause back when we used to | |
// debut with alerts and they coerce vars into strings | |
console.log(':: alert(d)') // :: alert(d) | |
alert(d) // > handler.get() Symbol(Symbol.toPrimitive) symbol | |
// > handler.get() toString string | |
// TargetProto.toString() | |
*/ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment