Last active
December 17, 2020 05:21
-
-
Save getify/4596011 to your computer and use it in GitHub Desktop.
A native syntax alternative for `Function.prototype.bind`? This is an open exploration and soft proposal. Feedback appreciated. The main problem I'm trying to solve with `Function.prototype.bind()` is that it creates a new function that's wrapped around the function you specify. This means if you do that a lot, you're creating (and throwing away…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function foo() { | |
console.log(this.bar); | |
} | |
function doSomething(fn, overrideThis) { | |
if (overrideThis) fn.call(overrideThis); | |
else fn(); | |
} | |
var bar = "bar1"; | |
var obj1 = { bar: "bar2" }; | |
var obj2 = { bar: "bar3" }; | |
foo(); // "bar1" | |
foo.call(obj1); // "bar2"; | |
var foo2 = foo.bind(obj1); // creates a whole new function... can be "ouch" for memory if done a lot | |
foo2 === foo; // false -- whole new function! | |
foo2(); // "bar2" | |
foo2.call(obj2); // "bar2" (not "bar3", `this` can't be overridden here) | |
doSomething( foo.bind(obj2) ); // "bar3" | |
doSomething( foo.bind(obj2), obj1 ); // "bar3" (`this` still can't be overriden) | |
// ATTENTION: new syntax proposal. | |
var foo3 = foo#obj1; // not a new function, just a special decorated reference to the same function | |
foo3 === foo; // true... same function! | |
foo3(); // "bar2" (defaulted `this` to `obj1`) | |
foo3.call(obj2); // "bar3" (`this` overridable, unlike Function.prototype.bind) | |
doSomething( foo#obj2 ); // "bar3" | |
doSomething( foo#obj2, obj1 ); // "bar2" (because `this` is still overridable) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@juanpodazo:
If the VM's were able to transparently make it so a new function wasn't actually being created, that'd be great, but I think it might be problematic in the converse way to how my proposal is being seen as possibly problematic.
For "legacy" reasons (if we can call ourselves in a post-ES5 era yet!),
bind()
has to return a function reference that's different than the original function, even if the VM is able to go so far as to literally reuse the same function in both instances. Maybe this reference faking/breaking is easy for VM's, maybe not. Not really sure. But could be an issue for them. I'm not sure how much of a perf win, if any, we'd get if the VM still had to create (and later GC) a shell function ("wrapper") just for maintaining these itinerantthis
bindings.Moreover, their
bind()
optimization, even if they worked out that concern, wouldn't, as we've said, address re-bindability, because again for legacy reasons,bind()
would have to return non-rebindable refs at the least.softBind
would still be necessary.I would obviously like to see both problems addressed, and if they can be addressed by the same mechanism, I'd consider that preferable.
I agree, we shouldn't complicate how references work.
But this would surely be an opaque change to references. It wouldn't be an observable (or mutable) "property" or anything like that. It's just simply a way of preserving with a reference the intended
this
binding. JS already has several other mechanisms for specifyingthis
, so I'm not sure that adding some rule/mechanism into that mix would really make references across the board any harder for devs to handle.Totally agreed. Not sure what you meant by "string" though. Typo?