I want to create a mixin that creates nested objects on the object that it mixes into.
For example
const mixin = {
top: {
middle: {
bottom: () => {
console.log(`Hello ${this.name}`);
}
}
}
};
const objectToBeMixed = {
name: 'Fred Bloggs'
};
Object.assign(objectToBeMixed, mixin);
objectToBeMixed.top.middle.bottom(); // Prints "Hello Fred Blogs"
Does anyone have an idea how to go about this, so that the "this" is bound to the objectToBeMixed?
That's not how you implement mixins. Instead of using a simple object, use a function that accepts context and merges the objects:
const mixin = context => Object.assign(context, {
top: {
middle: {
bottom: () => {
console.log(`Hello ${context.name}`);
}
}
}
});
const objectToBeMixed = {
name: 'Fred Bloggs'
};
mixin(objectToBeMixed);
objectToBeMixed.top.middle.bottom(); // Prints "Hello Fred Blogs"
There are a couple of possible issues there:
By using an arrow function, you're closing over this. But the this you're closing over won't refer to the object that you're mixing in. There are various ways to solve that (bind, etc.), but they involve making a deep copy of the mixin.
If you're going to use that mixin more than once, you probably want that deep copy for another reason, although of course it depends on your use case. If code creates properties on those objects, and they aren't deep copies, that will create cross-talk between the instances you're using it with. (If you're not going to make a deep copy, I'd freeze the objects in the mixin to prevent cross-talk by creating properties on them.)
Since the safest thing is to have separate objects for each target, I'd write a function that creates the mixin objects and applies them, with the bottom function closing over the target parameter. Something like this:
function applyX(target) {
const mixin = {
top: {
middle: {
bottom() {
console.log(`Hello ${target.name}`);
}
}
}
};
return Object.assign(target, mixin);
}
const objectToBeMixed = {
name: "Fred Bloggs"
};
applyX(objectToBeMixed);
objectToBeMixed.top.middle.bottom(); // Prints "Hello Fred Bloggs"