Skip to content

Instantly share code, notes, and snippets.

@andrewbridge
Last active August 23, 2017 11:02
Show Gist options
  • Save andrewbridge/7d862c1cb837aa661bba0b4ce6906f3d to your computer and use it in GitHub Desktop.
Save andrewbridge/7d862c1cb837aa661bba0b4ce6906f3d to your computer and use it in GitHub Desktop.
Access controlled variable in javascript using Proxy
/**
* LockableValue
*
* An object that can hold a value and control the read and write access to that value.
*
* Example:
* var VIPValue = new LockableValue();
* VIPValue.value = 'Really important, can't be changed';
* var release = VIPValue.lock(); // Default behaviour is to lock write access
* VIPValue.value = 'Something else'; // No change, a console error is shown
* var readRelease = VIPValue.lock({read: true});
* console.log(VIPValue.value); // Logs undefined, a console error is shown
*
* If the release function returned by lock isn't caught in a variable, it'll be impossible to unlock.
*/
function LockableValue() {
var locked = {read: false, write: false};
return new Proxy({
value: undefined,
lock: lock,
locked: locked
}, {
get: function(target, prop) {
if (locked.read && prop !== 'locked' && prop !== 'lock') {
console.error("This value is not gettable");
return;
}
if (prop === 'locked') {
return locked;
}
return target[prop];
},
set: function(target, prop, val) {
if (prop === 'lock' || prop === 'locked' || locked.write) {
console.error("This value is not settable");
//Could throw an exception here
return;
}
target[prop] = val;
}
});
function lock(config) {
if (typeof config !== 'object') {
config = {write: true};
}
//Copy the values so they can't be changed after the release is created
var _internalConfig = {read: Boolean(config.read), write: Boolean(config.write)};
// If it's already locked, someone else has the release, don't let someone else create an overriding release
if (_internalConfig.read === locked.read || _internalConfig.read !== true) {
delete _internalConfig.read;
}
if (_internalConfig.write === locked.write || _internalConfig.write !== true) {
delete _internalConfig.write;
}
changeLock(_internalConfig);
return changeLock.bind(this, _internalConfig, true);
}
function changeLock(config, unlock) {
if ('read' in config && config.read === true) {
locked.read = unlock ? !config.read : config.read;
}
if ('write' in config && config.write === true) {
locked.write = unlock ? !config.write : config.write;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment