Recursive function binding in a JavaScript object

Despite the rise of ES6 and especially the sacrosanct fat arrow syntax, JavaScript developers might still find themselves in need for Function.prototype.bind in some edge cases; binding all functions in an object to the same this value regardless of depth is one of them.

The example I have in mind is the building of a Vue.js plugin such as this one:

function install(Vue) {
Vue.mixin({
beforeCreate() {
this.$myPlugin = {
aMethod() {
console.log(this);
},

yet: {
anotherMethod() {
console.log(this);
}
}
};
}
});
}

export default { install };

Fairly logically, setting it up through Vue.use(MyPlugin) and calling this.$myPlugin.aMethod and this.$myPlugin.yet.anotherMethod yields a reference to the plugin object itself twice, which might not be what you want depending on what the plugin is supposed to do.

In such a situation, we therefore need to write a recursive binding function, which luckily is not all that hard:

function recursiveBind(obj, that) {
return Object.keys(obj).reduce((acc, key) => {
switch (typeof obj[key]) {
case "object":
return { ...acc, [key]: recursiveBind(obj[key], that) }; // recurse

case "function":
return { ...acc, [key]: obj[key].bind(that) }; // bind
}

return { ...acc, [key]: obj[key] }; // leave untouched
}, {});
}

All that remains to do then is to wrap our plugin object declaration with it:

function install(Vue) {
Vue.mixin({
beforeCreate() {
this.$myPlugin = recursiveBind({
aMethod() {
console.log(this);
},

yet: {
anotherMethod() {
console.log(this);
}
}
}, this);
}
});
}

And this now correctly refers to our Vue instance! Please share your plugin tips in the comment section, if any!