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)$/;