Bind order args

9 views
Skip to first unread message

kstubs

unread,
Aug 9, 2011, 2:43:47 PM8/9/11
to prototype-s...@googlegroups.com
Why, when I bind like this is "this" the 2nd argument (expecting it to be first argument) in the find function?

var mtedit = this.MeetEdits.find(function(mtedit,formid) {
return mtedit.meetid == formid;
}.bind(this, formid));

T.J. Crowder

unread,
Aug 10, 2011, 3:24:56 AM8/10/11
to Prototype & script.aculo.us
Can you explain your question a bit more clearly? Yes, it's true that
the `thisArg` argument to `Enumerable#find` is the second argument,
and it's also true that the `thisArg` argument to `Function#bind` is
the first argument, but it's unclear what you're really asking.

Also note that you don't need `bind` in your sample code at all,
because your iterator function is already a closure. So just

var mtedit = this.MeetEdits.find(function(item) {
return item.meetid == formid;
});

...because the function can use the `formid` variable from the
containing scope (I know it's there because you were passing it into
`bind`).

(I used `item` rather than `mtedit` as the function argument name to
avoid confusion with the `mtedit` variable in the containing scope.)

FWIW,
--
T.J. Crowder
Independent Software Engineer
tj / crowder software / com
www / crowder software / com

kstubs

unread,
Aug 11, 2011, 11:33:45 AM8/11/11
to prototype-s...@googlegroups.com
Well, and agreeably what I wrote seems a bit odd, however there are many cases when making "this" available to the anonomyous function is handy.  What I have found, is when I bind "this", then you lose scope of the containing context.  Take for example:

var x = 1;
vary array = [1,2,3,4];

array.each(function(num) {
  if (num == x) {      // x is out of scope, x is undefined
    // do something, involving "this"
  }.bind(this));

So, to bind this, and pass the value of x, the argument order seems to be backwards.

T.J. Crowder

unread,
Aug 11, 2011, 12:27:47 PM8/11/11
to Prototype & script.aculo.us
Hi,

In your example, `x` is in scope and will not be undefined within the
iterator, because the iterator function is a closure[1] over the
context containing `x`. The only reason `x` would be undefined would
be if you shadowed[2] it with a local declaration within your function
(either a var or a named function argument).

In that example, since your function is *already* a closure, there's
no particular need for `bind` anyway, just use a var pointing to
`this`:

var x = 1;
var array = [1,2,3,4];
var self = this; // or "me" is another popular name

array.each(function(num) {
  if (num == x) {
    // do something, involving "self"
  }
});

Or, of course, just use the fact that `each` accepts a second
argument[3] defining what `this` should be:

var x = 1;
var array = [1,2,3,4];

array.each(function(num) {
  if (num == x) {
    // do something, involving "this"
  }
},
this
);

`bind` is mostly useful when you're passing a function reference into
something that doesn't provide that second argument feature (like
`observe`) when you don't want to create a closure in the current
context.

There are, of course, many ways and it's down to the coder which they
prefer. :-)

[1] "Closures are not complicated"
http://blog.niftysnippets.org/2008/02/closures-are-not-complicated.html

[2] Variable shadowing
http://en.wikipedia.org/wiki/Variable_shadowing

[3] Enumerable#each
http://api.prototypejs.org/language/Enumerable/prototype/each/

HTH,
--
T.J. Crowder
Independent Software Engineer
tj / crowder software / com
www / crowder software / com

Reply all
Reply to author
Forward
0 new messages