27

A lot of people say that this is asked too much in the comments, which made me hesitant to ask this, but I still have not found a solution in their answers, mostly because (1) they are typically using jQuery and (2) the questions usually contain technicalities I do not understand.

I have a function with a variable inside. The variable is assigned a function. I'm sure this concept is not exclusive to AJAX, but that is the context I am using it in, if it makes a difference.

function iClick(this)
{
    var foo = "I would like to pass this.";

    ajax.onreadystatechange = function (foo) { alert(foo); }
}

I want to pass a variable into the function. However, since there is no original function declaration, how do I specify parameters? Can I even do that?

Tarik
  • 1,847
  • 4
  • 21
  • 30
  • 6
    +1. I say ask if you've searched but haven't found what you're looking for. A lot of us come from non-programming backgrounds so some computer science nuances and even fundamentals often need clarification (at least in my case). – orolo Oct 15 '10 at 21:31

5 Answers5

28

Just don't declare that variable as a parameter in your anonymous function, like this:

function iClick(this)
{
    var foo = "I would like to pass this.";
    ajax.onreadystatechange = function () { alert(foo); }
}

When you call the first parameter foo it's whatever's calling that callback passes in that's foo inside the function. If you want to reference a previously declared variable just do that, make sure not to use a parameter with the same name.

Nick Craver
  • 623,446
  • 136
  • 1,297
  • 1,155
  • 2
    Oh! I thought it would be out of it's scope. Thanks! – Tarik Oct 15 '10 at 21:18
  • 3
    @Tarik - JS has function scope and closures. Functions have access to the variables in parent scopes even after parent functions have returned. – Peter Ajtai Oct 15 '10 at 23:09
  • @PeterAjtai What if inside ajax.onreadystatechage I want to assign a new value to foo. Would that be visible in iClick() ? e.g. function iClick(this) { var foo = "I would like to pass this."; ajax.onreadystatechange = function () { foo = "Value changed"; } console.log(foo); // would this print 'Value changed' ? } – Ali Feb 07 '13 at 07:55
  • 2
    @Ali - No, because the `console.log(foo)` would get triggered immediately after `ajax.onreadystatechange = ...`, but the `onreadystatechange` itself would only get triggered at some future point in time........... so, it's all the same `foo`, but you have to consider the timing. – Peter Ajtai Feb 07 '13 at 17:21
  • 1
    Doesn't work: The variable stays available to the callback, but isn't save from being modified. Calling more than one callback won't work: https://jsfiddle.net/h5Loenfk/ – Sebastian Nov 10 '17 at 09:36
19

You can create a function like this

var c="hello";

(function(b){
   alert(b) 
})(c);

result would be "hello"

João Pimentel Ferreira
  • 14,289
  • 10
  • 80
  • 109
John Hartsock
  • 85,422
  • 23
  • 131
  • 146
  • 1
    that's the answer, and this is really useful when you want to parse a variable from outside into an async callback like `db.query` in node for instance – João Pimentel Ferreira Jan 13 '18 at 13:18
  • 1
    @JoãoPimentelFerreira Very simple to test. strange that you ask? But to answer. The c variable would the one that is in scope, which is the local version to the function. – John Hartsock Feb 02 '18 at 20:29
  • 1
    @JoãoPimentelFerreira Here is a simple test. https://jsfiddle.net/qon4cwhn/ You will see the the value of c as a global is not modified. – John Hartsock Feb 02 '18 at 20:36
  • very stupid question indeed :) Of course!!! the function is anonymously defined and immediately run, having the value of `c` parsed into the function local variable `b` – João Pimentel Ferreira Feb 02 '18 at 22:32
4

You can also do this, but maybe it's not necessary:

function iClick(this)
{
    var foo = "I would like to pass this.";

    ajax.onreadystatechange = (function(thevar) {
        return function () { alert(thevar); };
      })(foo);
}
Claudiu
  • 224,032
  • 165
  • 485
  • 680
1

As @John Hartsock referred, the answer that everyone should really remember is this

var c="hello";

(function(b){
   alert(b) 
})(c);

And that's very important for example in a for loop when there is some async function inside it, because otherwise you don't get the correct item.

Tell me, what comes out from here?

for (var i=0; i<5; i++){
  setTimeout(function(){ 
    console.log(i); 
    }, 1000);
}

Exactly: all 5, because when all the timers are triggered after 1 second, variable i is already at the value 5.

But if you use a self-invoked anonymous function (SIAF) like this

for (var i=0; i<5; i++){
  (function (j){
    setTimeout(function(){ 
      console.log(j); 
      }, 1000);
   })(i);
}

it does work, since every time the function is evoked, it runs another instance of the function and as any function, it has its own local variables. I do not merely define the function, I also run it right away (through the (); at the end), but then internally a new instance of the function will be created with different internal local variables, as I parse to the function a different variable every time I run it.

João Pimentel Ferreira
  • 14,289
  • 10
  • 80
  • 109
0

I belive you wanted something like that

function handleAjaxRequest(params) {
    var context = {'b':'inner', 'c': params['c']};
    function rendered(html) {
      // render
    }
    function gotPart(part) {
        context['a'] = part;
        engine.render(context).addCallback(rendered);
    }
    ajax.getPart(params).addCallback(gotPart);
}
vittore
  • 17,449
  • 6
  • 44
  • 82