Last active
August 23, 2017 11:02
-
-
Save andrewbridge/7d862c1cb837aa661bba0b4ce6906f3d to your computer and use it in GitHub Desktop.
Access controlled variable in javascript using Proxy
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
/** | |
* 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