Created
November 21, 2020 16:33
-
-
Save myfonj/9bda95fe3b2c08cc76da3306dbde9816 to your computer and use it in GitHub Desktop.
POC of JavaScript Object class with property order control via setBefore(pivot, key, value) and setFirst(key, value)
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
class FOJO { | |
constructor(o) { | |
this.object = Object.assign({}, o) | |
this.entries = Object.entries(this.object) | |
return new Proxy(this, this) | |
} | |
ownKeys() { | |
return Object.keys(this.object) | |
} | |
get(target, key) { | |
switch (key) { | |
case 'setFirst': return (key, value) => { | |
this.entries.unshift([key, value]) | |
this.object = Object.fromEntries(this.entries) | |
} | |
case 'setBefore': return (pivotKey, key, value) => { | |
if ((pivotKey in this.object) == false) { | |
throw "No." | |
} | |
let i = this.entries.findIndex(a => a[0] === pivotKey) | |
this.entries.splice(i, 0, [key, value]) | |
this.object = Object.fromEntries(this.entries) | |
} | |
default: return this.object[key] | |
} | |
} | |
set(target, key, value) { | |
if ((key in this.object) == false) { | |
this.object[key] = value | |
this.entries.push([key, value]) | |
return value | |
} | |
this.object[key] = value | |
this.entries = Object.entries(this.object) | |
return value | |
} | |
getOwnPropertyDescriptor(target, key, value) { | |
return Object.getOwnPropertyDescriptor(this.object, key) | |
} | |
} | |
var x = new FOJO({ two: 'second' }) | |
x.four = 'fourth' | |
x.setBefore('four', 'three', 'third') | |
x.setFirst('one', 'first') | |
x.five = 'fifth' | |
JSON.stringify(x, null, '\t') |
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
// <script> | |
// POC of Object class with property order control via setBefore(pivot, key, value) and setFirst(key, value) | |
// proxied "just enough to have getters, setters and JSON.stringify working" | |
// @see https://twitter.com/LeaVerou/status/1329793951973470214 | |
// @see https://twitter.com/myfonj/status/1329871558349901824 | |
// @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/Proxy | |
console.clear() | |
class FOJO { | |
constructor(o) { | |
console.log('constructor', arguments, this) | |
this.object = Object.assign({}, o) | |
this.entries = Object.entries(this.object) | |
return new Proxy(this, this) | |
} | |
ownKeys() { | |
// A trap for Object.getOwnPropertyNames and Object.getOwnPropertySymbols. | |
console.log('ownKeys', arguments, this) | |
return Object.keys(this.object) | |
} | |
get(target, key) { | |
// A trap for getting property values. | |
console.log('get', arguments, this) | |
switch (key) { | |
case 'setFirst': return (key, value) => { | |
this.entries.unshift([key, value]) | |
this.object = Object.fromEntries(this.entries) | |
} | |
case 'setBefore': return (pivotKey, key, value) => { | |
if ((pivotKey in this.object) == false) { | |
throw "No." | |
} | |
let i = this.entries.findIndex(a => a[0] === pivotKey) | |
this.entries.splice(i, 0, [key, value]) | |
this.object = Object.fromEntries(this.entries) | |
} | |
default: return this.object[key] | |
} | |
} | |
set(target, key, value) { | |
// A trap for setting property values. | |
console.log('set', arguments, this) | |
if ((key in this.object) == false) { | |
this.object[key] = value | |
this.entries.push([key, value]) | |
return value | |
} | |
this.object[key] = value | |
this.entries = Object.entries(this.object) | |
return value | |
} | |
apply(target, key, value) { | |
// A trap for a function call. | |
console.log('apply', arguments, this) | |
} | |
construct(target, key, value) { | |
// A trap for the new operator. | |
console.log('construct', arguments, this) | |
} | |
defineProperty(target, key, value) { | |
// A trap for Object.defineProperty. | |
console.log('defineProperty', arguments, this) | |
} | |
deleteProperty(target, key, value) { | |
// A trap for the delete operator. | |
console.log('deleteProperty', arguments, this) | |
} | |
getOwnPropertyDescriptor(target, key, value) { | |
// A trap for Object.getOwnPropertyDescriptor. | |
console.log('getOwnPropertyDescriptor', arguments, this) | |
return Object.getOwnPropertyDescriptor(this.object, key) | |
} | |
getPrototypeOf(target, key, value) { | |
// A trap for Object.getPrototypeOf. | |
console.log('getPrototypeOf', arguments, this) | |
} | |
has(target, key, value) { | |
// A trap for the in operator. | |
console.log('has', arguments, this) | |
} | |
isExtensible(target, key, value) { | |
// A trap for Object.isExtensible. | |
console.log('isExtensible', arguments, this) | |
} | |
preventExtensions(target, key, value) { | |
// A trap for Object.preventExtensions. | |
console.log('preventExtensions', arguments, this) | |
} | |
setPrototypeOf(target, key, value) { | |
// A trap for Object.setPrototypeOf. | |
console.log('setPrototypeOf', arguments, this) | |
} | |
} | |
var x = new FOJO({ two: 2 }) | |
x.four = 4 | |
x.setBefore('four', 'three', 3) | |
x.setFirst('one', 1) | |
x.five = 5 | |
console.log(JSON.stringify(x)) | |
// == '{"one":1,"two":2,"three":3,"four":4,"five":5}' | |
// </script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment