Alternative to Function.bind
On Mar 22, 2009, at 11:11 PM, Igor Bukanov wrote:
Various current proposals for Function.bind have a drawback that in a typical situation one needs to use the reference to the object twice as in
obj.method.bind(obj)
This double-referencing can be avoided if bind would be applied to the object, not to the function. The result of the bind call would be a view of the object that translates any function property of the object into a bound function so obj.method.bind(obj) could be written as
obj.bind().method
Even shorter form can be archived if bind would not be a function but rather a getter-property so the above can be written as
obj.bind.method
With such short form the need, for example, for Array methods taking an extra thisObj argument would be pretty much removed.
This actually sounds like a great idea. As a matter of fact, implementing this in ES3 seems quite trivial:
// Either with Obejct.prototype.bind
Object.prototype.bind = function(methodName) { var object = this; return function(){ return object[methodName].apply(object, arguments); } };
var o = { foo: function(){ return this.bar; }, bar: 'Boo' };
o.bind('foo')(); // "Boo"
// or an alternative approach, which I like even more
Function.bind = function(object, methodName) { return function(){ return object[methodName].apply(object, arguments); } };
Function.bind(o, 'foo')(); // "Boo"
Here is one way to implement object.bind.method using ES3.1
Object.defineProperty(Object.prototype, 'bind', { enumerable: false, writable: false, configurable: false, get: function() { var rv = {}; // this would need to use Object.getOwnPropertyNames and // recursively check Object.getPrototypeOf for (var key in this) { if (typeof this[key] == 'function') { rv[key] = this[key].bind(this); } } Object.freeze(rv); Object.seal(rv); Object.preventExtensions(rv); return rv; } });
This does not create proxies for getters or setters nor values. It does seal, freeze and prevent extensions on the bind proxy so that it is clearer that it is not the object itself that you are operating on. Another option is to replace all the "methods" on the object with the bound methods.
Anyway, this is just an example of the power of the ES3.1 meta programming.
2009/3/26 Juriy Zaytsev <kangax at gmail.com>:
On Thu, Mar 26, 2009 at 11:01 PM, Erik Arvidsson <erik.arvidsson at gmail.com> wrote:
Here is one way to implement object.bind.method using ES3.1
Hi Erik, this is a really cool example! A few minor nits...
Object.defineProperty(Object.prototype, 'bind', { enumerable: false, writable: false,
For a getter/setter property as you're defining here, there is no writeable: attribute. Rather, the right way to make it read-only is
set: undefined,
configurable: false, get: function() { var rv = {}; // this would need to use Object.getOwnPropertyNames and // recursively check Object.getPrototypeOf for (var key in this) { if (typeof this[key] == 'function') { rv[key] = this[key].bind(this); } } Object.freeze(rv); Object.seal(rv); Object.preventExtensions(rv);
freeze() implies seal() and preventExtensions(), so these last two lines are harmless but not needed.
-----Original Message----- From: es-discuss-bounces at mozilla.org [mailto:es-discuss- bounces at mozilla.org] On Behalf Of Mark S. Miller
For a getter/setter property as you're defining here, there is no writeable: attribute. Rather, the right way to make it read-only is ... set: undefined,
configurable: false,
However, undefined is the default value for a set function if none is specified and since configurable is being set to false it is probably fine to simply leave out the set attribute. Of course configurable defaults to false, but in that case it is probably better to be explicit about the intent.
On Mar 22, 2009, at 8:11 PM, Igor Bukanov wrote:
Various current proposals for Function.bind have a drawback that in a typical situation one needs to use the reference to the object twice as in
obj.method.bind(obj)
This is common, but not majority-case from a quick survey:
$ find dojotoolkit.org MochiKit prototypejs.org -name '.js' -print |
xargs fgrep .bind( | wc -l
40
$ find dojotoolkit.org MochiKit prototypejs.org -name '.js' -print |
xargs fgrep .bind( | /tmp/findbind.pl | wc -l
18
where findbind.pl looks for /\b(\w+).\w+.bind(\1[,)]/
(obj.method.bind(obj...).
Anyway, bind is being standardized based on the de-facto standard, the
common intersection semantics among popular Ajax libraries' bind-like
methods (jQuery has a different bind so I left it out of my find above).
obj.bind.method
With such short form the need, for example, for Array methods taking an extra thisObj argument would be pretty much removed.
This is cool, although perhaps the name should be something else:
obj.bindSelfTo.method
or just
obj.bindTo.method
Don't want to get all long-winded, but do want to avoid overloading
the ever-popular "bind".
2009/3/27 Erik Arvidsson <erik.arvidsson at gmail.com>:
Here is one way to implement object.bind.method using ES3.1
The provided example has a drawback that obj.bind would not work with methods that are added to obj later. So it would not be the true bounded-method view for obj but rather a snapshot.
I suspect that to implement such view in ES one would need something like those catch-all proposals to implement a getter for non-existing properties.
Igor
2009/3/27 Brendan Eich <brendan at mozilla.com>:
although perhaps the name should be something else:
obj.bindSelfTo.method
or just
obj.bindTo.method
IMO a better name would be boundedMethods or just bounded to emphasis that the result is a view that may work with any method like in:
var obj2 = obj.bounded; ... array.sort(obj2.my_sort); array.filter(obj2.my_filter);
Igor
On Mar 27, 2009, at 11:42 AM, Igor Bukanov wrote:
2009/3/27 Brendan Eich <brendan at mozilla.com>:
although perhaps the name should be something else:
obj.bindSelfTo.method
or just
obj.bindTo.method
IMO a better name would be boundedMethods or just bounded to emphasis that the result is a view that may work with any method like in:
var obj2 = obj.bounded;
Mathemitcally speaking, a good word, but probably one of
"obj.autoBind" or "obj.selfBound" is better.
You are right that this wants catch-alls, as do all the tiered
virtualization sandbox schemes in the works and out there. We should
get back to discussing catch-alls -- I have a draft saved somewhere...
On Fri, Mar 27, 2009 at 17:23, Brendan Eich <brendan at mozilla.com> wrote:
You are right that this wants catch-alls, as do all the tiered virtualization sandbox schemes in the works and out there. We should get back to discussing catch-alls -- I have a draft saved somewhere...
With catch-alls a real live proxy could be made where all methods are bound. (This should be doable with SpiderMonkey today... I see a blog post coming up :0)
Various current proposals for Function.bind have a drawback that in a typical situation one needs to use the reference to the object twice as in
obj.method.bind(obj)
This double-referencing can be avoided if bind would be applied to the object, not to the function. The result of the bind call would be a view of the object that translates any function property of the object into a bound function so obj.method.bind(obj) could be written as
obj.bind().method
Even shorter form can be archived if bind would not be a function but rather a getter-property so the above can be written as
obj.bind.method
With such short form the need, for example, for Array methods taking an extra thisObj argument would be pretty much removed.
Igor