Skip to content

Instantly share code, notes, and snippets.

@shesek
Created February 27, 2012 09:37
Show Gist options
  • Save shesek/1922813 to your computer and use it in GitHub Desktop.
Save shesek/1922813 to your computer and use it in GitHub Desktop.
JavaScript per-instance private storage area
# A simple implementation to get a private storage area for objects.
# Also allows setting default properties for the storage area.
# Written in CoffeeScript: (with an added `export` function. On the regular version, use `exports.privates = ...`)
export privates = do ->
counter=0
(proto) ->
key = "__id#{ ++counter }"
store = []
(object) -> store[object[key] ||= store.length] ||= Object.create proto or null
# (Object.create shim required for it to work on ES3)
###
# JavaScript Version
(function(exports) {
var counter = 0;
exports.privates = function(proto) {
var key = '__id' + ++counter,
store = [];
return function(object) {
var idx = (object[key] || (object[key] = store.length));
return store[idx] || (store[idx] = Object.create(proto||null));
}
}
})(exports||window);
###
class Hello
private = privates
say: (text) -> console.log "Say: #{ text }"
world: 'World'
talk: -> private(this).say "Hello, #{private(this).world}"
setWorld: (value) -> private(this).world = value
code = new Hello
code.setWorld 'Code'
code.talk() # Say: Hello, Code
world = new Hello
world.talk() # Say: Hello, World
# Obviosuly, doesn't work with a different copy of the private() function
private = privates()
private(world).world = 'Foobar'
world.talk() # Still 'World'.
# However, while its impossible to read/write data to private areas, it is possible to replace the property used to
# track internal index.
world['__id1'] = code['__id1']
world.talk() # Say: Hello, //code//.
# This is fixable by either using the ECMAScript.next WeakMap (only on Mozilla 6 and highly experimental) instead of
# storing the internal index as a property, or by using ECMAScript5 Object.defineProperty() to set the property's
# attributes writable, configurable and enumerable to false (only FF4+, Chrome5+, IE9+ and Safari5+). It'll take some
# time until WeakMap are used widely enough to be considered for client-side production, and defining the property
# attributes won't work on, as usual, the majority of IE users - making it not 100% secure on the client side, but it
# works well on server-side environments like NodeJS and Rhino.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment