To deep-freeze all enumerable properties (ES2015+):
// Recursively freeze an object
const deepFreeze = x => {
Object.freeze(x)
Object.values(x).forEach(deepFreeze)
}
If you have circular references:
// Recursively freeze an object with circular references
const deepFreeze = x => {
Object.freeze(x)
Object.values(x).filter(x => !Object.isFrozen(x)).forEach(deepFreeze)
}
If you also have to deep-freeze any shallow-frozen stuff (slightly slower):
// Recursively deep freeze an object with circular references
const deepFreeze = (x, frozen = []) => {
if (frozen.includes(x)) return null
frozen.push(x)
Object.freeze(x)
Object.values(x).forEach(x => deepFreeze(x, frozen))
}
tldr; Two-liner:
const deepFreeze = (x, frozen = []) => frozen.includes(x) ||
frozen.push(Object.freeze(x)) && Object.values(x).forEach(x => deepFreeze(x, frozen))