views:

128

answers:

5

Should 'this' in the following code not still refer to the DOM object selected by the MooTools selector?

        $$('div').addEvent('click', function()
        {
            var click1 = function(){$(this).setStyle('background', 'red');}
            click1();
        });
A: 

No. click1() isn't associated with any object (it's not e.g. callable as obj.click1()), so in it this refers to the window.

However, you can do:

click1.call(this);

The call method basically sets this to its first parameter.

Matthew Flaschen
To be clear it that should read it sets `this` to it's *first* parameter :)
Nick Craver
A: 

You'll need to do this instead to refer to the element you want:

click1.call(this);

Otherwise this refers to window inside the function, you can see the working version here.

Nick Craver
@Downvoter - care to comment? The alternative answer provided is more expensive for this particular example, saying what's *wrong* with this answer might actually help others.
Nick Craver
Sure, this will work but it's not the MooTools way of doing stuff. Chrys is using a JS framework for a reason.
Oskar Krawczyk
well, if you are talking expensive, then perhaps the whole thing should be refactored. for example, if the function is not being re-used, there's no sense in saving it. using `$(this)` in mootools is redundant, this is not jquery - especially in the context of a callback from an event where the element would have been extended already. using `.bind` or `.pass` are chainable mootools methods that allow binding+passing of arguments. I would argue `expensive` in the context of an extra function call is not an issue (unless animating)--code legibility+best framework practices are more important.
Dimitar Christoff
@Dimitar - Using a more expensive route for something that can be done in vanilla JavaScript with the same amount of code is "best framework practices"...really? Neither of you have explained what's *wrong* with the answer, and more importantly, the other answer *fails to answer the question*. The author asked what `this` would be, as he has it, it would be `window` inside his `click1()` call, but the @Oskar's answer failed to mention that. Sure it's a good practice to go that way for *most* things, but you start by answering the question...
Nick Craver
well, clearly you know your mootools so I will just take your word for it.
Dimitar Christoff
@Dimitar - You seemed to have missed my point entirely, it's a *JavaScript closure question*, regardless of framework, as it's written, `this` won't maintain context in `call1`...regardless of which framework you're using...
Nick Craver
no, i have not missed your point but you need to look at the bigger picture. the answer could have simply been `'this' will be window`. the reason why we are having this argument at all is that since mootools is class-centric development, people go out of their way in order to keep `this` referencing the class instance even in event callbacks and achieve it through the '.bind' wrap, amongst other ways. showing how to change scopes is far more useful, imo. anyway - no skin off my nose.
Dimitar Christoff
+2  A: 

You should do it the MooTools way - by binding this to the click1 function - http://jsfiddle.net/oskar/7EArh/5/

$$('div').addEvent('click', function() {
    var click1 = function() {
        this.setStyle('background', 'red');
    }.bind(this);
    click1();
});​

Also this is already extended with MooTools methods, so there is no need for doing $(this).

Oskar Krawczyk
+1 and also, mootools way: `click1.run(args, this);` - > check http://mootools.net/docs/core/Native/Function#Function:run and the other `Function` methods.
Dimitar Christoff
+2  A: 

The cleanest way to handle it is this:

var click1 = function() {
    this.setStyle('background', 'red');
};

$$('div').addEvent('click', click1);

in the above, 'this' get's passed to the function called.

Working example: http://jsfiddle.net/gT5dc/

shanebo
A: 

In this kind of crazy situation, I just do:

$$('blah').addEvent('click', function() { var self = this;

var click1 = function(){ self.setStyle(....); }
click1();

});

... of course. mostly none of my code would include a click1(); at the end. These kind of inner functions like click1 would normally be used for some other purpose. for e.g.

var click1 = function(){ self.addClass('blah2').removeClass('blah'); } self.set('tween', { onComplete: click1 }).fade('in');

Rajeev J Sebastian