Water Cooler v2
Water Cooler v2

Reputation: 33850

JavaScript functions inside of JavaScript functions, closures, et al

When I declare OnSuccess inside another function like below, the browser developer tools console indicates an error that there's no function called OnSuccess in the global scope. From this, I infer that any functions declared like below inside another function are still hoisted/pinned/treated as functions of the HTML DOM window object.

Then, I declare OnError like you declare a member inside an object initializer. That doesn't work either.

One way I could do is move both OnError and OnSuccess outside the AssignBackupOnServer function, but I want the OnSuccess and OnError to be able to look at the local variables of the AssignBackupOnServer, so I have declared it within the AssignBackupOnServer function.

What's the right way of going about this declaration if I want the contained lambda to exhibit a closure on the captured variables of its containing/enclosing function?

function AssignBackupOnServer(mainGuyUId, backupUId, backupFirstName, backupLastName) {

    var url = '/Foo/SearchForBackup';

    $.ajax(url,
        {
            cache: false,
            async: false,
            type: 'POST',
            data: JSON.stringify(
            { 
              'mainGuyUId': mainGuyUId, 
              'backupUId': backupUId, 
              'backupFirstName': backupFirstName, 
              'backupLastName': backupLastName 
            }),
            dataType: 'json',
            contentType: 'application/json',
            success: AssignBackupOnServer.OnSuccess,
            error: AssignBackupOnServer.OnError
        });

    function OnSuccess(data, textStatus, jqXHR) {
        // I want to use mainGuyUId, backupUId, 
        // backupFirstName, and backupLastName
        // here and therefore, I want this function
        // to exhibit a closure on its containing lambda
        // so I have declared it here
    }

    OnError : function(jqXHR, textStatus, errorThrown) {
    }
}

Upvotes: 0

Views: 71

Answers (3)

Maroshii
Maroshii

Reputation: 4017

For what I see you are willing to reuse the onSuccess and onError functions but access the outer variables. If that's not the case Richard's answer is what you need. If it is I would suggest a more functional approach:

function makeSuccess(mainGuyUId, backupUId, backupFirstName, backupLastName){
  return function(data, textStatus, jqXHR){
    // Here you have access to everything
    // and you can use the function elsewhere
  }
}

function makeError(mainGuyUId, backupUId, backupFirstName, backupLastName){
  return function(jqXHR, textStatus, errorThrown){
    // Here you have access to everything
    // and you can use the function elsewhere
  }
}

function AssignBackupOnServer(mainGuyUId, backupUId, backupFirstName, backupLastName) {
  var args = Array.prototype.slice.call(arguments);
  var url = '/Foo/SearchForBackup';

  $.ajax(url,
    {
      //...
      success: makeSuccess.apply(this,args),
      error: makeError.apply(this,args)
    });
}

Upvotes: 0

JaredPar
JaredPar

Reputation: 754763

The best way to handle this is to declare an identifier in the function AssignBackupOnServer for both functions and use those identifiers directly intstead of AssignBackupOnServer. For example

function onSuccess(data, textStatus, jqXHR) { 
  ...
}

function onError(jqXHR, textStatus, errorThrown) { 
  ...
}

$.ajax(url,
        {
         ...
            success: onSuccess,
            error: onError
        });

Upvotes: 1

Richard Dalton
Richard Dalton

Reputation: 35793

You were close with the OnSuccess but just slightly wrong when referencing it. You don't need the AssignBackupOnServer. prefix:

    success: OnSuccess,
    error: OnError
});

function OnSuccess(data, textStatus, jqXHR) {
}

function OnError(jqXHR, textStatus, errorThrown) {
}

Upvotes: 1

Related Questions