Skip to content

Instantly share code, notes, and snippets.

@abezhinaru
Last active July 19, 2017 12:07
Show Gist options
  • Save abezhinaru/a9edf875b4238dc70a151d0034901b8c to your computer and use it in GitHub Desktop.
Save abezhinaru/a9edf875b4238dc70a151d0034901b8c to your computer and use it in GitHub Desktop.
/**
*
* Creating configurable property
*
* @param {Object} obj - Object to which should be assigned a new property
*
* @param {String} name - property name
* @param {object} descriptor - property settings
* @param {Function} descriptor.get - fn fires when receive prop value
* @param {Function} descriptor.set - fn fires when assign value to prop
* @param {Object} descriptor.default - Initial value for descriptor.
*/
const descriptor = (obj, name, descriptor) => {
Object.defineProperties(obj, {
[`_${name}`]: {
enumerable: false,
configurable: true,
writable: false,
value: descriptor.default || true
},
[name]: {
enumerable: true,
configurable: false,
get: () => {
descriptor.get && descriptor.get(obj[`_${name}`]);
return obj[`_${name}`];
},
set: (val) => {
if (descriptor.final) return;
setWritable(obj, `_${name}`, true);
obj[`_${name}`] = val;
setWritable(obj, `_${name}`, false);
descriptor.set && descriptor.set(val);
}
}
});
obj[name] = descriptor.hasOwnProperty('default') ? descriptor.default : true;
};
/**
* Change value of writable at descriptor if a prop configurable=true
*
* @param {Object} obj - Object in which should be changed prop 'writable' at descriptor
* @param {String} name - property name
* @param {Boolean} isWritable - value of writable prop
*/
const setWritable = (obj, name, isWritable) => {
let descr = Object.getOwnPropertyDescriptor(obj, name);
if (descr.configurable) {
descr.writable = isWritable;
Object.defineProperty(obj, name, descr);
}
};
let car = {};
descriptor(car, 'weight', {final: true, default: 2000});
descriptor(car, 'color', {final: true, default: 'coral'});
descriptor(car, 'driver', {default: 'Jason Statham'});
car.weight = 10;
car.color = 'white';
car.driver = 'Andrey Bezhinaru';
console.log(car.weight); // 2000
console.log(car.color); // coral
console.log(car.driver); // Andrey Bezhinaru instead of 'Jason Statham'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment