librelist archives

« back to archive

Backbone, jQuery and scopes

Backbone, jQuery and scopes

From:
Marcin Szczepanski
Date:
2011-10-29 @ 04:49
Thought I'd pose a question to the list.  I haven't actually done much 
research into the question myself, so bare with me if I'm being an noob 
about it!

I've been using a bit of Backbone and jQuery lately, and a common pattern 
might be something like:

[Backbone View]
foo: function()
{
  $("li", this.el).each(function() {
	.. something ..
   });
}

So now, how in the "something" how do I reference the Backbone view, since
"this" is now the element being iterated over?

I have been doing:

foo: function() 
{
  var context = this;
  $("li", this.el).each(function() {
    context.model.get("blah");
  }
}

While this works, it feels like it might be wrong. At best "context" isn't
really the best name for the var. Is it?  Opinions? Arguments? 

Thanks! :)

- Marcin

Re: [sydjs] Backbone, jQuery and scopes

From:
David Chambers
Date:
2011-10-29 @ 05:15
I suggest using `Function::bind`:

*foo: function() {*
*  $('li', this.el).each(function() {*
*    this.model.get('blah')*
*  }.bind(this))*
*}*

This is of course far easier to read when written in CoffeeScript:

*foo: ->*
*  $('li', @el).each =>*
*    @model.get 'blah'*

You'll need a polyfill to support old browsers (and IE):

   -
   
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind#section_5
   - https://github.com/kriskowal/es5-shim/blob/c89adef/es5-shim.js#L38-170

Inspiration:

   -
   
http://blip.tv/jsconf/jsconf2011-andrew-dupont-everything-is-permitted-extending-built-ins-5211542

David


On 28 October 2011 21:49, Marcin Szczepanski <marcins@gmail.com> wrote:

> Thought I'd pose a question to the list.  I haven't actually done much
> research into the question myself, so bare with me if I'm being an noob
> about it!
>
> I've been using a bit of Backbone and jQuery lately, and a common pattern
> might be something like:
>
> [Backbone View]
> foo: function()
> {
>  $("li", this.el).each(function() {
>        .. something ..
>   });
> }
>
> So now, how in the "something" how do I reference the Backbone view, since
> "this" is now the element being iterated over?
>
> I have been doing:
>
> foo: function()
> {
>  var context = this;
>  $("li", this.el).each(function() {
>    context.model.get("blah");
>  }
> }
>
> While this works, it feels like it might be wrong. At best "context" isn't
> really the best name for the var. Is it?  Opinions? Arguments?
>
> Thanks! :)
>
> - Marcin
>

Re: [sydjs] Backbone, jQuery and scopes

From:
Dominic Tarr
Date:
2011-10-29 @ 05:00
'context' or 'self' is correct. that is just what you have to do in
javascript.

On Sat, Oct 29, 2011 at 3:49 PM, Marcin Szczepanski <marcins@gmail.com>wrote:

> Thought I'd pose a question to the list.  I haven't actually done much
> research into the question myself, so bare with me if I'm being an noob
> about it!
>
> I've been using a bit of Backbone and jQuery lately, and a common pattern
> might be something like:
>
> [Backbone View]
> foo: function()
> {
>  $("li", this.el).each(function() {
>        .. something ..
>   });
> }
>
> So now, how in the "something" how do I reference the Backbone view, since
> "this" is now the element being iterated over?
>
> I have been doing:
>
> foo: function()
> {
>  var context = this;
>  $("li", this.el).each(function() {
>    context.model.get("blah");
>  }
> }
>
> While this works, it feels like it might be wrong. At best "context" isn't
> really the best name for the var. Is it?  Opinions? Arguments?
>
> Thanks! :)
>
> - Marcin
>

Re: [sydjs] Backbone, jQuery and scopes

From:
David Chambers
Date:
2011-10-29 @ 05:18
>
> 'context' or 'self' is correct. that is just what you have to do in
> javascript.


You don't *have to* do this in JavaScript. In fact, function context binding
is arguably more idiomatic.

David


On 28 October 2011 22:00, Dominic Tarr <dominic.tarr@gmail.com> wrote:

> 'context' or 'self' is correct. that is just what you have to do in
> javascript.
>
>
> On Sat, Oct 29, 2011 at 3:49 PM, Marcin Szczepanski <marcins@gmail.com>wrote:
>
>> Thought I'd pose a question to the list.  I haven't actually done much
>> research into the question myself, so bare with me if I'm being an noob
>> about it!
>>
>> I've been using a bit of Backbone and jQuery lately, and a common pattern
>> might be something like:
>>
>> [Backbone View]
>> foo: function()
>> {
>>  $("li", this.el).each(function() {
>>        .. something ..
>>   });
>> }
>>
>> So now, how in the "something" how do I reference the Backbone view, since
>> "this" is now the element being iterated over?
>>
>> I have been doing:
>>
>> foo: function()
>> {
>>  var context = this;
>>  $("li", this.el).each(function() {
>>    context.model.get("blah");
>>  }
>> }
>>
>> While this works, it feels like it might be wrong. At best "context" isn't
>> really the best name for the var. Is it?  Opinions? Arguments?
>>
>> Thanks! :)
>>
>> - Marcin
>>
>
>

Re: [sydjs] Backbone, jQuery and scopes

From:
Ben Taylor
Date:
2011-10-29 @ 05:34
Problem: Local this context is often overridden when using event handlers,
for loops and other callbacks.

A Selection of Solutions:

1. Using the effects of closures to "save" the local this in a different variable:

var self = this;
$("blah").each(function(){
  self.doStuff(this);
});

2. Using underscore (http://documentcloud.github.com/underscore/#bind) to 
bind the function's this 

$("blah").each( _.bind((function(el){
  this.doStuff(el);
}), this));

3. Similar approach using underscore but abstracting the anonymous 
function to a method

$("blah").each(_.bind(this.doStuff, this)); 

4. Again but reusable

//constructor
this.boundDoStuff = _.bind(this.doStuff, this);

//elsewhere
$("blah").each(this.boundDoStuff);



5. CoffeeScript with anonymous function

$("blah").each (el) =>
  @doStuff el

6. CoffeeScript with method

#method definition
doStuff: (el) =>
  #do things with el

#elsewhere
$("blah").each @doStuff



Each of these approaches is mostly acceptable. My favourite is 
CoffeeScript with a combination of anonymous functions and methods 
(depending on how complex each task is). Though Underscore also works 
quite well and is often combined with Backbone.

The first approach is the traditional JQuery way of solving this problem.

 - Ben


On Saturday, 29 October 2011 at 4:18 PM, David Chambers wrote:

> > 'context' or 'self' is correct. that is just what you have to do in 
javascript.
> 
> 
> You don't have to do this in JavaScript. In fact, function context 
binding is arguably more idiomatic. 
> 
> David
> 
> 
> On 28 October 2011 22:00, Dominic Tarr <dominic.tarr@gmail.com 
(mailto:dominic.tarr@gmail.com)> wrote:
> > 'context' or 'self' is correct. that is just what you have to do in 
javascript.
> > 
> > 
> > On Sat, Oct 29, 2011 at 3:49 PM, Marcin Szczepanski <marcins@gmail.com
(mailto:marcins@gmail.com)> wrote:
> > > Thought I'd pose a question to the list.  I haven't actually done 
much research into the question myself, so bare with me if I'm being an 
noob about it!
> > > 
> > > I've been using a bit of Backbone and jQuery lately, and a common 
pattern might be something like:
> > > 
> > > [Backbone View]
> > > foo: function()
> > > {
> > >  $("li", this.el).each(function() {
> > >        .. something ..
> > >   });
> > > }
> > > 
> > > So now, how in the "something" how do I reference the Backbone view,
since "this" is now the element being iterated over?
> > > 
> > > I have been doing:
> > > 
> > > foo: function()
> > > {
> > >  var context = this;
> > >  $("li", this.el).each(function() {
> > >    context.model.get("blah");
> > >  }
> > > }
> > > 
> > > While this works, it feels like it might be wrong. At best "context"
isn't really the best name for the var. Is it?  Opinions? Arguments?
> > > 
> > > Thanks! :)
> > > 
> > > - Marcin
> > 
> 

Re: [sydjs] Backbone, jQuery and scopes

From:
Michael McGlynn
Date:
2011-11-01 @ 23:03
A comprehensive list of solutions, you can also use jQuery.proxy to execute
a function with a given scope.

http://jimmycuadra.com/posts/understanding-jquery-14s-proxy-method
http://api.jquery.com/jQuery.proxy/


On Sat, Oct 29, 2011 at 4:34 PM, Ben Taylor <taybenlor@gmail.com> wrote:

> Problem: Local this context is often overridden when using event handlers,
> for loops and other callbacks.
>
> A Selection of Solutions:
>
> 1. Using the effects of closures to "save" the local this in a different
> variable:
>
> var self = this;
> $("blah").each(function(){
>   self.doStuff(this);
> });
>
> 2. Using underscore <http://documentcloud.github.com/underscore/#bind> to
> bind the function's this
>
> $("blah").each( _.bind((function(el){
>   this.doStuff(el);
> }), this));
>
> 3. Similar approach using underscore but abstracting the anonymous
> function to a method
>
> $("blah").each(_.bind(this.doStuff, this));
>
> 4. Again but reusable
>
> //constructor
> this.boundDoStuff = _.bind(this.doStuff, this);
>
> //elsewhere
> $("blah").each(this.boundDoStuff);
>
> 5. CoffeeScript with anonymous function
>
> $("blah").each (el) =>
>   @doStuff el
>
> 6. CoffeeScript with method
>
> #method definition
> doStuff: (el) =>
>   #do things with el
>
> #elsewhere
> $("blah").each @doStuff
>
>
> Each of these approaches is mostly acceptable. My favourite is
> CoffeeScript with a combination of anonymous functions and methods
> (depending on how complex each task is). Though Underscore also works quite
> well and is often combined with Backbone.
>
> The first approach is the traditional JQuery way of solving this problem.
>
>  - Ben
>
> On Saturday, 29 October 2011 at 4:18 PM, David Chambers wrote:
>
>  'context' or 'self' is correct. that is just what you have to do in
> javascript.
>
>
> You don't *have to* do this in JavaScript. In fact, function context
> binding is arguably more idiomatic.
>
> David
>
>
> On 28 October 2011 22:00, Dominic Tarr <dominic.tarr@gmail.com> wrote:
>
> 'context' or 'self' is correct. that is just what you have to do in
> javascript.
>
>
> On Sat, Oct 29, 2011 at 3:49 PM, Marcin Szczepanski <marcins@gmail.com>wrote:
>
> Thought I'd pose a question to the list.  I haven't actually done much
> research into the question myself, so bare with me if I'm being an noob
> about it!
>
> I've been using a bit of Backbone and jQuery lately, and a common pattern
> might be something like:
>
> [Backbone View]
> foo: function()
> {
>  $("li", this.el).each(function() {
>        .. something ..
>   });
> }
>
> So now, how in the "something" how do I reference the Backbone view, since
> "this" is now the element being iterated over?
>
> I have been doing:
>
> foo: function()
> {
>  var context = this;
>  $("li", this.el).each(function() {
>    context.model.get("blah");
>  }
> }
>
> While this works, it feels like it might be wrong. At best "context" isn't
> really the best name for the var. Is it?  Opinions? Arguments?
>
> Thanks! :)
>
> - Marcin
>
>
>
>
>

Re: [sydjs] Backbone, jQuery and scopes

From:
David Chambers
Date:
2011-11-02 @ 01:35
If you care about creating idiomatic code, please don't use `_.bind` or
`jQuery.proxy` or any of the other functions that perform this job. Use a
polyfill for `Function::bind` and write code like this:

*    this.foo()*
*    bar(function (qux) {*
*      this.baz()*
*      qux(function () {*
*        alert(this.quxx)*
*      }.bind(this))*
*    }.bind(this))
*
It's ugly as fuck, but this is how the language was designed to be used (or
perhaps this aspect of the language was not designed at all). Obviously,
the CoffeeScript equivalent is far more readable:

*    @foo()*
*    bar (qux) =>*
*      @baz()*
*      qux =>*
*        alert @quxx*

David


On 1 November 2011 16:03, Michael McGlynn <micmcg@gmail.com> wrote:

> A comprehensive list of solutions, you can also use jQuery.proxy to
> execute a function with a given scope.
>
> http://jimmycuadra.com/posts/understanding-jquery-14s-proxy-method
> http://api.jquery.com/jQuery.proxy/
>
>
> On Sat, Oct 29, 2011 at 4:34 PM, Ben Taylor <taybenlor@gmail.com> wrote:
>
>> Problem: Local this context is often overridden when using event
>> handlers, for loops and other callbacks.
>>
>> A Selection of Solutions:
>>
>> 1. Using the effects of closures to "save" the local this in a different
>> variable:
>>
>> var self = this;
>> $("blah").each(function(){
>>   self.doStuff(this);
>> });
>>
>> 2. Using underscore 
<http://documentcloud.github.com/underscore/#bind>to bind the function's 
this
>>
>> $("blah").each( _.bind((function(el){
>>   this.doStuff(el);
>> }), this));
>>
>> 3. Similar approach using underscore but abstracting the anonymous
>> function to a method
>>
>> $("blah").each(_.bind(this.doStuff, this));
>>
>> 4. Again but reusable
>>
>> //constructor
>> this.boundDoStuff = _.bind(this.doStuff, this);
>>
>> //elsewhere
>> $("blah").each(this.boundDoStuff);
>>
>> 5. CoffeeScript with anonymous function
>>
>> $("blah").each (el) =>
>>   @doStuff el
>>
>> 6. CoffeeScript with method
>>
>> #method definition
>> doStuff: (el) =>
>>   #do things with el
>>
>> #elsewhere
>> $("blah").each @doStuff
>>
>>
>> Each of these approaches is mostly acceptable. My favourite is
>> CoffeeScript with a combination of anonymous functions and methods
>> (depending on how complex each task is). Though Underscore also works quite
>> well and is often combined with Backbone.
>>
>> The first approach is the traditional JQuery way of solving this problem.
>>
>>  - Ben
>>
>> On Saturday, 29 October 2011 at 4:18 PM, David Chambers wrote:
>>
>>  'context' or 'self' is correct. that is just what you have to do in
>> javascript.
>>
>>
>> You don't *have to* do this in JavaScript. In fact, function context
>> binding is arguably more idiomatic.
>>
>> David
>>
>>
>> On 28 October 2011 22:00, Dominic Tarr <dominic.tarr@gmail.com> wrote:
>>
>> 'context' or 'self' is correct. that is just what you have to do in
>> javascript.
>>
>>
>> On Sat, Oct 29, 2011 at 3:49 PM, Marcin Szczepanski <marcins@gmail.com>wrote:
>>
>> Thought I'd pose a question to the list.  I haven't actually done much
>> research into the question myself, so bare with me if I'm being an noob
>> about it!
>>
>> I've been using a bit of Backbone and jQuery lately, and a common pattern
>> might be something like:
>>
>> [Backbone View]
>> foo: function()
>> {
>>  $("li", this.el).each(function() {
>>        .. something ..
>>   });
>> }
>>
>> So now, how in the "something" how do I reference the Backbone view,
>> since "this" is now the element being iterated over?
>>
>> I have been doing:
>>
>> foo: function()
>> {
>>  var context = this;
>>  $("li", this.el).each(function() {
>>    context.model.get("blah");
>>  }
>> }
>>
>> While this works, it feels like it might be wrong. At best "context"
>> isn't really the best name for the var. Is it?  Opinions? Arguments?
>>
>> Thanks! :)
>>
>> - Marcin
>>
>>
>>
>>
>>
>