Function.prototype.ary

Like what _.ary has done in Lodash, we just need a method to create another function like Function.prototype.bind and accept up to n arguments specified by the parameter:

function mapper(value, index) {
    console.log(index); // => undefined
    return value * 2;
}

[1, 2, 3].map(mapper.ary(null, 1)); // => [2, 4, 6]

This should be helpful to eliminate the side effect of unexpected parameters like:

const div = document.createElement('div');
div.innerText = 'text';
document.body.appendChild(div);

// To eliminate the side effect of the unexpected parameter `event`
document.body.addEventListener('click', handler.ary(null, 0));

function handler(display) {
    div.style.display = display ?? div.offsetParent == null ? 'block' : 'none';
}

handler(1); // show specifically

You can already achieve that with arrow functions, which are often as concise as the proposed Function.prototype.ary, but also more versatile.

[1, 2, 3].map(x => mapper(x))

document.body.addEventListener('click', () => handler());
1 Like

Assume that there is a callback function with multiple parameters, and we hope to only use the first several:

task(done.ary(null, 3)); // only use the first three parameters
task((arg1, arg2, arg3) => done(arg1, arg2, arg3)); 

Function.prototype.ary seems like more convenient.

task(done.ary(null, 3));
task((a, b, c) => done(a, b, c))

Doesn’t seem that much more convenient, and denies you the opportunity to name the params well to convey their meaning (ie, to convey why you’re only passing these three), and to destructure them as well if needed.

1 Like

You can convey the meaning of parameters inside the defined handler itself:

const done = (named1: renamed1, named2, name3) => { /* ... */ };
task(done.ary(null, 3));

Can't you...just do this?

const done = (renamed1, named2, name3) => { /* ... */ };
task((named1, named2, name3) => done(named1, named2, name3));
task(done.ary(null, 3));
task((...a) => done(...a.slice(0, 3));

// https://github.com/tc39/proposal-slice-notation
task((...a) => done(...a[:3]));

Code may be more complicated? And destructuring always lead to much more code after babel.

Unless you need to support IE, you don't need to transpile destructuring into raw property accesses.