export default function compose(...fns) {Many D3 plugins are intended to be invoked by selection.call,
meaning that they produce a function that can be configured and then passed
to selection.call. For example, d3-axis provides a number of
constructors (axisLeft, axisTop, etc.) that all produce an
axis, which is a function. It is also an object with methods for
modifying the scale and ticks.
compose takes a list of functions, fns, intended to be passed to
selection.call and returns a function that when passed to selection.call
invokes each function in turn, from right to left, as if they were passed to
selection.call one at a time. The attributes of fns are merged into the
returned object.
export default function compose(...fns) {Construct a new function that when called enumerates over the functions in the composition and applies each in turn.
let f = function(...args) {
for (let f of fns) {
f.apply(this, args);
}
};The new function is now assigned each of the attributes from the source functions.
for (let source of fns) {
for (let k in source) {
if (!nonEnumerableProps.test(k)) {
f[k] = source[k];
}
}
}Reverse the order of the functions so that they are applied from right to left.
fns = fns.reverse();
return f;
}These properties are not to be touched during the merge.
const nonEnumerableProps = /^(valueOf|isPrototypeOf|to(Locale)?String|propertyIsEnumerable|hasOwnProperty)$/;