Proposal: Function.prototype.bindContext

Andrea Giammarchi andrea.giammarchi at gmail.com
Thu Sep 17 19:03:19 UTC 2020


I've found myself (once again) polluting the `Function.prototype` with a
lazy method that, once invoked, grants that the returned bound function is
always the same, per context.

# Use Case

It's still a common footgun to add events either via `context.method` or
via `context.method.bind(context)`, where the former footgan would invoke
`method` with a global context/undefined instead of the expected context,
while the latter would make it impossible to ever remove that listener
later on.

It's also common to use methods for timers sensitive things, and it's
indeed not by accident that `console` got "self bound", or provided as
namespace, when it used to throw if `setTimeout(console.log, 100, value)`
was used, for example.

# Proposal

Provide a lazy `bindContext` method that grants that if a method/function
bound the same context before, it always returns the same reference.

# Implementation / Polyfill (lazy version)

```js
Function.prototype.bindContext = function (context) {
  const _ = new WeakMap;
  this.bindContext = bindContext;
  return bindContext.call(this, context);
  function bindContext(context) {
    if (!_.has(context))
      _.set(context, this.bind(context));
    return _.get(context);
  }
};
```

# Implementation details

As the method suggest, and differently from `bind`, `bindContext` accepts
only one argument, and it should throw with any context that is primitive
(boolean, number, string, undefined, null), like any WeakMap key would
throw as well.

# Why not user-land / libraries / helpers

Because standardizing a well-known/needed utility to not footgun common
patterns would make the debate regarding global prototypes pollution
irrelevant, as it's the standard that helps us out.

In a few words, this might erase tons of common mistakes, but it also could
be simplified within some helper/library, as long as not all of them need
to include the proposed polyfill through a package or another.

Thanks for consideration 👋
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20200917/f0550247/attachment.html>


More information about the es-discuss mailing list