function bindRootContext(obj, context = obj) {
return new Proxy(obj, {
get(target, key) {
const val = target[key];
return (
val instanceof Function ? val.bind(Object.hasOwn(target, key) ? context : target) :
val instanceof Object ? bindRootContext(val, context) :
val
);
},
});
}
const obj = bindRootContext({
name: 'Root',
a: {
name: 'A',
logName() { console.log(this.name); },
b: {
name: 'B',
logName() { console.log(this.name); },
arr: [
{
name: '666',
logName() { console.log(this.name); },
},
function() { console.log(this.name); },
],
c: {
name: 'C',
logName() { console.log(this.name); },
},
},
},
});
obj.a.b.c.logName(); // Root
obj.a.b.logName(); // Root
obj.a.logName(); // Root
obj.a.b.arr[0].logName(); // Root
obj.a.b.arr[1](); // Root