Skip to content

Instantly share code, notes, and snippets.

@lawrencegripper
Forked from moehlone/make_writable.js
Last active July 12, 2023 23:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lawrencegripper/b69b8fa0f25116c25d4c5f2257bd10c9 to your computer and use it in GitHub Desktop.
Save lawrencegripper/b69b8fa0f25116c25d4c5f2257bd10c9 to your computer and use it in GitHub Desktop.
Make JavaScript readonly propertys writable (example for overwriting navigator.userAgent; useful for unit tests -> browser detection)
/**
* Creates a read/writable property which returns a function set for write/set (assignment)
* and read/get access on a variable
*
* @param {Any} value initial value of the property
*/
function createProperty(value) {
var _value = value;
/**
* Overwrite getter.
*
* @returns {Any} The Value.
* @private
*/
function _get() {
return _value;
}
/**
* Overwrite setter.
*
* @param {Any} v Sets the value.
* @private
*/
function _set(v) {
_value = v;
}
return {
"get": _get,
"set": _set
};
};
/**
* Creates or replaces a read-write-property in a given scope object, especially for non-writable properties.
* This also works for built-in host objects (non-DOM objects), e.g. navigator.
* Optional an initial value can be passed, otherwise the current value of the object-property will be set.
*
* @param {Object} objBase e.g. window
* @param {String} objScopeName e.g. "navigator"
* @param {String} propName e.g. "userAgent"
* @param {Any} initValue (optional) e.g. window.navigator.userAgent
*/
function makePropertyWritable(objBase, objScopeName, propName, initValue) {
var newProp,
initObj;
if (objBase && objScopeName in objBase && propName in objBase[objScopeName]) {
if(typeof initValue === "undefined") {
initValue = objBase[objScopeName][propName];
}
newProp = createProperty(initValue);
try {
Object.defineProperty(objBase[objScopeName], propName, newProp);
} catch (e) {
initObj = {};
initObj[propName] = newProp;
try {
objBase[objScopeName] = Object.create(objBase[objScopeName], initObj);
} catch(e) {
// Workaround, but necessary to overwrite native host objects
}
}
}
};
makePropertyWritable(window, "navigator", "userAgent");
window.navigator.userAgent = "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10136";
console.log(window.navigator.userAgent);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment