/    Sign up×
Community /Pin to ProfileBookmark

self = this … or how I learned to continue worrying but love closures

so here’s a *greatly simplified* snippet:
it uses the YUI event handler functions… if you don’t know them then suffice it to say that:

YAHOO.util.Event.on ( el , sType , fn , obj , override )
Appends an event handler

Parameters:
el <String|HTMLElement|Array|NodeList> An id, an element reference, or a collection of ids and/or elements to assign the listener to.
sType <String> The type of event to append
fn <Function> The method the event invokes
obj <Object> An arbitrary object that will be passed as a parameter to the handler
override <Boolean|object> If true, the obj passed in becomes the execution scope of the listener. If an object, this object becomes the execution scope.

[code]
function TopLevel() {
function MyProblematicClass() {
// here is why it is problematic:
var self = null;

var myObjectHandler = function(action, args) {
var myProblematicFunction() {
var myDiv = document.createElement(‘div’);

// here is where I use ‘self’ because ‘this’ did not work
YAHOO.util.Event.on(myDiv, ‘click’, function() {
this.someFunction();
}, null, self);

return myDiv;
}

switch(action) {
case ‘myAction’:
//here I define ‘self’ to be ‘this’
self = this;

// here (the same scope as above!), ‘this’ *does* work
this.someOtherFunction(myProblematicFunction());
break;
default:
}
}

return new objectThatDefines_someFunction_and_someOtherFunction({
objectHandler: myObjectHandler
});
}

var myObj = new MyProblematicClass();
myObj.callToThingWhichFiresTheHandler();
}
[/code]

the call to myObj.callToThingWhichFiresTheHandler() doesn’t actually occur where I placed it, but I think this is enough to post my question.

I can only assume that my problem lies in the fact that I instead of keeping to standard closure procedure I decided to return a reference to some newly created object. However, the code *does* work, so I really don’t understand what the problem is.

If you want to get into slightly deeper specifics, the objectThatDefines_someFunction_and_someOtherFunction
is actually the ycarousel component found at [url]http://www.billwscott.com/carousel/[/url]

to post a comment
JavaScript

8 Comments(s)

Copy linkTweet thisAlerts:
@epimethauthorMay 23.2008 — anybody at all?
Copy linkTweet thisAlerts:
@epimethauthorMay 29.2008 — one last hopeful bump....
Copy linkTweet thisAlerts:
@toicontienMay 29.2008 — Shouldn't:
var myProblematicFunction() {
var myDiv = document.createElement('div');

<i> </i> // here is where I use 'self' because 'this' did not work
<i> </i> YAHOO.util.Event.on(myDiv, 'click', function() {
<i> </i> this.someFunction();
<i> </i> }, null, self);

<i> </i> return myDiv;
<i> </i> }

Be:
[B]var myProblematicFunction = function()[/B] {
var myDiv = document.createElement('div');

<i> </i> // here is where I use 'self' because 'this' did not work
<i> </i> YAHOO.util.Event.on(myDiv, 'click', function() {
<i> </i> this.someFunction();
<i> </i> }, null, self);

<i> </i> return myDiv;
<i> </i> }
Copy linkTweet thisAlerts:
@epimethauthorMay 29.2008 — yes it should, and it is so in the production code.

You wouldn't happen to have any insight on the question itself, though?

thanks for at least reading it... I get the feeling that this is just a little out of most people's league :-)
Copy linkTweet thisAlerts:
@toicontienMay 29.2008 — function TopLevel() {
function MyProblematicClass() {
// here is why it is problematic:
var self = null;

<i> </i>var myObjectHandler = function(action, args) {
<i> </i> var myProblematicFunction = function() {
<i> </i> var myDiv = document.createElement('div');

<i> </i> // here is where I use 'self' because 'this' did not work
<i> </i> YAHOO.util.Event.on(myDiv, 'click', function() {
<i> </i> this.someFunction(); [B]/* (1) */[/B]
<i> </i> }, null, self); [B]/* (2) */[/B]

<i> </i> return myDiv;
<i> </i> }

<i> </i> switch(action) {
<i> </i> case 'myAction':
<i> </i> //here I define 'self' to be 'this'
<i> </i> self = this;

<i> </i> // here (the same scope as above!), 'this' *does* work
<i> </i> this.someOtherFunction(myProblematicFunction()); [B]/* (3) */[/B]
<i> </i> break;
<i> </i> default:
<i> </i> }
<i> </i>}

<i> </i>return new objectThatDefines_someFunction_and_someOtherFunction({
<i> </i> objectHandler: myObjectHandler
<i> </i>});
}

var myObj = new MyProblematicClass();
myObj.callToThingWhichFiresTheHandler();
}


[B](1)[/B]

The "this" keyword is referring to the myDiv variable in myProblematicFunction. Because "self" is null, what scope should the function be executed in? I bet if null is passed as the last parameter to the Event.on function, the function is executed in the window scope maybe? I haven't had much experience with YUI.

[B](2)[/B]

The "this" keyword refers to myProblamaticFunction, if you had used "this" instead of "self".

[B](3)[/B]

The "this" keyword refers MyProblematicClass.

Is this also what you are thinking?
Copy linkTweet thisAlerts:
@epimethauthorMay 29.2008 — since you don't know the yui, I'll explain quickly what YAHOO.util.Event.on does. This will answer questions 1 and 2... I'll touch on them again after the explanation

1st argument:

the element in your html (either string elementId or a reference to the object)

in my case its the div I just created

2nd argument:

which event you want

in my case its 'onclick'

3rd argument:

a reference to a function

in my case I create an anonymous function right then and there

4th argument:

any extra argument that you want sent to the function. this arguments are references (or copies of primitive variables... standard javascript fare) from within the current scope.

in my case, just null suffices.

5th argument: (here's the kicker!)

the scope in which you want to execute the function, or 'true' if you want to use the argument from 4 as the scope. ie, what the 'this' keyword refers to from within the function's scope.

in my case, I want the function to have access to 'someFunction' and all of the other variables and functions that exist inside the scope of 'objectThatDefines......otherFunction'. So in order for my program to work, I set it to 'self'


so. to answer your questions:

1) no, here 'this' refers to 'self'. 'self' was defined as 'this' back when myObjectHandler() was called.

2) no, 'this' actually refers to 'window'. As for my understanding, it *should* refer to the object created by objectThatDefines_someFunction_and_someOtherFunction instantiated when MyProblematicClass was instantiated.

3) no, 'this' refers to objectThatDefines_someFunction_and_someOtherFunction because that is what is returned when new MyProblematicClass is instantiated.


lets add some asserts, shall we?

<i>
</i>function TopLevel() {
function MyProblematicClass() {
// here is why it is problematic:
var self = null;

<i> </i>// assert(this == [object MyProblematicClass])

<i> </i>var myObjectHandler = function(action, args) {
<i> </i> var myProblematicFunction = function() {
<i> </i> var myDiv = document.createElement('div');

<i> </i> // assert(this == window)

<i> </i> // here is where I use 'self' because 'this' did not work
<i> </i> YAHOO.util.Event.on(myDiv, 'click', function() {
<i> </i> this.someFunction();
<i> </i> }, null, self);

<i> </i> return myDiv;
<i> </i> }

<i> </i> switch(action) {
<i> </i> case 'myAction':
<i> </i> //here I define 'self' to be 'this'
<i> </i> self = this;

<i> </i> // assert(this == [object objectThatDefines......otherFunction])

<i> </i> // here (the same scope as above!), 'this' *does* work
<i> </i> this.someOtherFunction(myProblematicFunction());

<i> </i> break;
<i> </i> default:
<i> </i> }
<i> </i>}

<i> </i>return new objectThatDefines_someFunction_and_someOtherFunction({
<i> </i> objectHandler: myObjectHandler
<i> </i>});
}

var myObj = new MyProblematicClass();
myObj.callToThingWhichFiresTheHandler();
}
Copy linkTweet thisAlerts:
@epimethauthorMay 29.2008 — just a little addition to the dillema:

changing:
<i>
</i> this.someOtherFunction(myProblematicFunction());

to:
<i>
</i> this.someOtherFunction(myProblematicFunction.call(this));


corrects the scope issue and 'self' need not be created.

in the YUI call, instead of 'self' we use 'this' for the same results
Copy linkTweet thisAlerts:
@epimethauthorJun 02.2008 — I know I said its my last bump, but the last bump brought someone new to the conversation. If this one doesn't work I won't bump again!
×

Success!

Help @epimeth spread the word by sharing this article on Twitter...

Tweet This
Sign in
Forgot password?
Sign in with TwitchSign in with GithubCreate Account
about: ({
version: 0.1.9 BETA 5.18,
whats_new: community page,
up_next: more Davinci•003 tasks,
coming_soon: events calendar,
social: @webDeveloperHQ
});

legal: ({
terms: of use,
privacy: policy
});
changelog: (
version: 0.1.9,
notes: added community page

version: 0.1.8,
notes: added Davinci•003

version: 0.1.7,
notes: upvote answers to bounties

version: 0.1.6,
notes: article editor refresh
)...
recent_tips: (
tipper: @AriseFacilitySolutions09,
tipped: article
amount: 1000 SATS,

tipper: @Yussuf4331,
tipped: article
amount: 1000 SATS,

tipper: @darkwebsites540,
tipped: article
amount: 10 SATS,
)...