Last active
November 7, 2016 21:14
-
-
Save towerofnix/de91f087b43d83171eaf62cedb1f1183 to your computer and use it in GitHub Desktop.
Why is this so fast
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
const createObject = function() { | |
const properties = new Map() | |
let prototype = null | |
const obj = { | |
get: function(key, bindFunction = true) { | |
let value | |
// If we don't have this property, and we do have a prototype, search | |
// the prototype. For prototype searching bindFunction is false, since we | |
// can't rebind a function. | |
if (properties.has(key)) { | |
value = properties.get(key) | |
} else if (prototype) { | |
value = prototype.get(key, false) | |
} else { | |
value = undefined | |
} | |
// Functions should be bound to "this".. unless we're not at the top of | |
// the prototype chain! | |
if (bindFunction && value instanceof Function) { | |
value = value.bind(obj) | |
} | |
return value | |
}, | |
set: function(key, val) { | |
properties.set(key, val) | |
return val | |
}, | |
setPrototype: function(protoObj) { | |
prototype = protoObj | |
} | |
} | |
return obj | |
} | |
const createObjectProxy = function() { | |
const properties = new Map() | |
let prototype = null | |
let shouldBindFunction = true | |
return new Proxy({}, { | |
get: function(target, key, proxy) { | |
if (key === '__NO_FN_BIND_NEXT__') { | |
shouldBindFunction = false | |
return | |
} | |
if (properties.has(key)) { | |
value = properties.get(key) | |
} else if (prototype) { | |
prototype.__NO_FN_BIND_NEXT__ | |
value = prototype[key] | |
} else { | |
value = undefined | |
} | |
if (shouldBindFunction && value instanceof Function) { | |
value = value.bind(proxy) | |
} | |
// Reset should bind function incase __NO_FN_BIND_NEXT__ was used | |
shouldBindFunction = true | |
return value | |
}, | |
set: function(target, key, value) { | |
properties.set(key, value) | |
}, | |
setPrototypeOf: function(target, proto) { | |
prototype = proto | |
return true | |
} | |
}) | |
} | |
const timeit = function(msg, times, fn) { | |
const old = Date.now() | |
for (let i = 0; i < times; i++) { | |
fn() | |
} | |
const time = Date.now() - old | |
console.log(`${msg} * ${times}: ${time}ms`) | |
} | |
timeit('Custom library', 1000000, () => { | |
const cat = createObject() | |
cat.set('sayName', function() { | |
this.get('name') | |
}) | |
const mark = createObject() | |
mark.setPrototype(cat) | |
mark.set('name', 'Mark') | |
mark.get('sayName')() | |
}) | |
timeit('Custom library (proxy syntax)', 1000000, () => { | |
const cat = createObjectProxy() | |
cat.sayName = function() { | |
this.name | |
} | |
const mark = createObjectProxy() | |
Object.setPrototypeOf(mark, cat) | |
mark.name = 'Mark' | |
mark.sayName() | |
}) | |
timeit('Native JS', 1000000, () => { | |
const cat = { | |
sayName: function() { | |
this.name | |
} | |
} | |
const mark = Object.create(cat) | |
mark.name = 'Mark' | |
mark.sayName() | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Safari Results
Safari Conclusions
Proxy
s are STILL TERRIBLE and you should REALLY STILL NEVER use them.