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() | |
}) |
Firefox Results
Custom library * 1000000: 2965ms
Custom library (proxy syntax) * 1000000: 11336ms
Native JS * 1000000: 2690ms
Custom library * 10000000: 30013ms
Custom library (proxy syntax) * 10000000: 107851ms
Native JS * 10000000: 27432ms
Firefox Conclusion
- JavaScript's native prototype system is okay I guess.
- JavaScript's native
Proxy
s are TERRIBLE and you should NEVER EVER EVER use them. - For the best performance, be smart and stick to native JavaScript stuff.
Safari Results
Custom library * 1000000: 1802ms
Custom library (proxy syntax) * 1000000: 3597ms
Native JS * 1000000: 963ms
Custom library * 10000000: 14900ms
Custom library (proxy syntax) * 10000000: 33182ms
Native JS * 10000000: 9421ms
Safari Conclusions
- JavaScript's native prototype system is pretty fast.
- JavaScript's native
Proxy
s are STILL TERRIBLE and you should REALLY STILL NEVER use them. - For the best performance, be smart and stick to native JavaScript stuff.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Chrome Results
Chrome Conclusion
Proxy
s are slow.