views:

121

answers:

8

I have the following JavaScript code:

function parentFunc() {

    function childFunc() {
        ...
    }

    ...
}

// outside of myParentFunc, how do I call myChildFunc() ?
childFunc(); // doesn't work

How do I call childFunc() from outside of parentFunc()?

UPDATE:

I know the obvious answer would be to move childFun outside of parentFun, but this is a third party library that I can't modify.

A: 

Just declare it outside the function o_O

Well, if the library doesn't provide a way to do it, modify it and upload it with your .js, probably the library doesn't allow you to do it because you shouldn't.

M28
I can't because I am linking to a third party library. So I can't modify the code.
CraigWl
I edited the answer.
M28
+2  A: 

This would be one way you could do it.

var myChildFunction;

function myParentFunc() {
  //....
  myChildFunction = function () {
    //....
  }
  myChildFunction();
}

myChildFunction();

Here is another way

var myChildFunction = function () {
  //....    
}


function myParentFunc() {
  //....
  myChildFunction();
}

myChildFunction();
John Hartsock
This won't work until you call the parent function.
SLaks
The second instance will work with out calling the parent function. Take your pick and determine what works best in your situration.
John Hartsock
A: 
function parentFunc() {

    var childFunc = function() {
        ...
    }

    ...
}

childFunc(); // works
Coronatus
Actually it doesn't.
Tgr
This won't work because JavaScript has function scope. childFunc is only "visible" inside parentFunc.
Stephano
Thanks, I didn't know that.
Coronatus
+3  A: 

See exposing inner functions to the outer world.

KMan
+2  A: 

You may want to consider using the Yahoo Module Pattern instead:

myModule = function () {

    //"private" variables:
    var myPrivateVar = "I can be accessed only from within myModule."

    //"private" methods:
    var myPrivateMethod = function () {
        console.log("I can be accessed only from within myModule");
    }

    return {
        myPublicProperty: "I'm accessible as myModule.myPublicProperty."

        myPublicMethod: function () {
            console.log("I'm accessible as myModule.myPublicMethod.");

            //Within myModule, I can access "private" vars and methods:
            console.log(myPrivateVar);
            console.log(myPrivateMethod());
        }
    };
}();

You define your private members where myPrivateVar and myPrivateMethod are defined, and your public members where myPublicProperty and myPublicMethod are defined.

You can simply access the public methods and properties as follows:

myModule.myPublicMethod();    // Works
myModule.myPublicProperty;    // Works
myModule.myPrivateMethod();   // Doesn't work - private
myModule.myPrivateVar;        // Doesn't work - private
Daniel Vassallo
Looks very interesting. So what's the code to make this work without having to use the YUI library?
CraigWl
@CraigWl: That snippet works as is. Simply replace the methods and properties with meaningful stuff. You do not need YUI. It is called the YUI Module pattern because it was first used by Yahoo for YUI.
Daniel Vassallo
+2  A: 

If you absolutely cannot modify the code, there is no way to do it. Otherwise assign the inner function to something you can access, by changing the line

function childFunc() {

to, say,

window.cf = childFunc() {

then you can access the function through the cf variable. (There are many other ways to do it; this is the one that requires the least change in the third-party code.)

Tgr
Wow, you should never ever ever ever modify the window object. Why not just make your own object to modify?
Stephano
Stephano, do you realize that every time you make a global variable you are adding to the window object, just as in the example above?
rob
If JavaScript decides to put all the global variables in a different place someday, what does that code do? It's aways good form to keep your hands out of the cookie jar :) .
Stephano
You have to modify the window object to have your own object (or variable). The only difference is that `window.cf` will always refer to your global `cf` variable, but omitting that and just writing `cf` could refer to any variable with the same name somewhere in the scope chain. It is better programming practice to take the "risk" that once the JavaScript language is changed your script will break along with all the others but protect against accidental name conflicts which would result in some unknown variable in some unknown part of the code changing instead of the one you wanted to write.
Tgr
A: 

Here is what you can do:

attach the inner function to global:

function parentFunc() {

   window.childFunc = function(){

   }

}

This is kind of ghetto though :)

So I would use some of the more sophisticated OO patterns, such as the module patter:

function parentFunc() {

   var someVar;

   var childFunc = function(){

   };


   return {
      childFunc,
      someVar
   }

}

parentFunc.childFunc();

This way you can return your inner function and your return value.

Remember, the fact that you cannot call your inner function, is a feature of JS not a limitation.

Dave
+1  A: 

There is a way to do this very simply, but it is also a very bad practice to get into. However, because OCCATIONALLY global variables are handy, I'll mention this. Please note that in the situation you are describing is not a good example of using global variables.

The following code will work but is horrible code.

function parentFunction() {
    ...
    childFunction = function() {
    ...
    }
}

childFunction();

You are making childFunction global, which is generally a horrible idea. Using namespaces is a way to get around the global variable insanity.

ABV = {};
ABV.childFunction = function() {
    ...
}
ABV.parentFunction = function() {
    ...
    ABV.childFunction();
    ...
}
ABV.childFunction();

This is how libraries like DWR and such work. they use 1 global variable and put all their children inside that one global variable.

Thinking about how scope works in JavaScript is really important. If you start throwing global variables around you are bound to run into lots of trouble. From the example you are using, it is clear that you need something like a class of "functions" that you can call from anywhere. Hope that helps.

Stephano