views:

84

answers:

4

If I want to give a JavaScript variable global scope I can easily do this:

var myVar;

function functionA() {
    myVar = something;
}

Is there a similarly simple and clean way -- without creating an object -- to separate the "declaring" and the "defining" of a nested function? Something like:

function functionB;       // declared with global scope

function functionA() {

    functionB() {        // nested, would have local scope if declared here
        CODE;
    }
}

I should clarify that I'm referring to the scope of the function name itself -- so that if it is in an iframe it can be called from a script in the parent document. (Nothing to do with scope of variables inside nested functions.)

A: 

You can kind of do what you want.

You can create a function that acts like a namespace for properties and methods, and then you could essentially call either...

functionB();

or

functionA.functionB();

There is an article on how to do it here:

http://www.stevefenton.co.uk/Content/Blog/Date/201002/Blog/JavaScript-Name-Spacing/

In response to the update...

Is the iframe on the same domain as the parent site? You can't call JavaScript across the domain boundary, which may explain the problem.

Sohnee
See my comment in roosteronacid's answer... Tx
nesting season
All same domain (actually on local computer). I do have roosteronacid's code working though now... Thnx
nesting season
+1  A: 

You can create global variables and functions by creating instances on the window object:

function _A()
{
    // scoped function
    function localFunctionInTheScopeOf_A()
    {
    }

    // global function
    window.globalFunctionOutsideTheScopeOf_A = function ()
    {
    };
}

In your case, though, all you need to do is this:

var myFn; // global scope function declaration

function randomFn()
{
    myFn = function () // global scope function definition
    {
    };
}

Note: It is never a good idea to clog up the global scope. If you can; I'd recommend that you re-think how your code works, and try to encapsulate your code.

roosteronacid
I've updated the original question to clarify that I'm trying to access a nested function in the script of an iframe, from a parent script. I've tried both these syntaxes, but the parent script doesn't seem to be able to call the nested iframe function with them -- e.g. IFRAMEREFERENCE.contentWindow.myFn does nothing, IFRAMEREFERENCE.contentWindow.myFn() gives error no such function.
nesting season
OK I have figured out that I need to run randomFn() first, to get the code of myFn "evaluated" (?), and then I can call myFn() from the parent without any problem.
nesting season
So this function expression code does answer and solve the original question fully. Thanks for your help.
nesting season
Good. Please accept my answer then, and revert your question to the original one.
roosteronacid
+1  A: 

Perhaps I'm misunderstanding the question, but it sounds like you want something like this:

var innerFunc;

function outerFunc() {
    var foo = "bar";

    innerFunc = function() {
        alert(foo);
    };
}
Tim Down
See my response to roosteronacid. I need to call this nested function in an iframe, from a parent document. I don't think there's any way to call your "innerFunc" in this way?
nesting season
Yes there is: any global variable (such as `innerFunc` here) becomes a property of the global object, mapped to the window object in browsers. `document.getElementById("your_iframe").contentWindow.innerFunc()` will do it.
Tim Down
OK I have figured out that I need to run outerFunc() first, to get the code of innerFunc "evaluated" (?), and then I can call innerFunc() from the parent without any problem.
nesting season
So this function expression code does answer and solve the original question fully. Thanks for your help.
nesting season
+1  A: 

You cannot globalize variables/functions cross windows/iframes that way. Each window/iframe has it's own global scope and to target variables/functions in another window/iframe, you need explicit accessor code and conform to the same origin policy. Only variables/functions inside the windows/iframes global scope are accessible.

code in top window.

var iframe = document.getElementById('iframeId');
var iframeContext = iframe.contentWindow || iframe;

// this will only work if your iframe has completed loading
iframeContext.yourFunction();

You could also possibly define functions/variables in the top window instead and simply work in one scope by binding the stuff you need from the iframe through a closure. Again, assuming you meet the same origin policy. This will not work cross domain.

code in iframe.

var doc = document;
var context = this;
top.myFunction = function(){
    // do stuff with doc and context.
}

It is also important to note, that you need to check if your iframe content and it's scripts are fully loaded. Your top page/window will inadvertidly be done and running before your iframe content is done, ergo variables/functions might not be declared yet.

As for exposing a private function, others have awnsered this, but copy/pasting for completeness.

var fnB;
var fnA = function(){
    var msg = "hello nurse!";
    fnB = function(){
         alert(msg);
    }
}

I have the habbit of declaring stand alone functions as variables (function expression) and only use function statements to signify constructors/pseudo-classes. It also avoids a few possible embarrasing mistakes.. In any case, fnB resides in the global scope of the iframe and is available to the top window.

Why exactly you want this beats me, seems it makes matters more complicated to debug or update a few months later.

BGerrissen
ISSUE 1. You say: *"You can't globalize [...] functions cros windows/iframes that way"*. I'm suspecting that this is the answer to my question. A function in an iframe must be both declared and defined in the global whitespace of the iframe script for a parent script to be able to call it.
nesting season
ISSUE 2. You say: *"You can't globalize variables [... in ...] iframes that way"*. For variables in an iframe, it does of course work to declare them in global whitespace and define them locally. Perhaps you are referring to some advanced syntax to "expose" a locally-declared variable to the global scope of the iframe...?
nesting season
ISSUE 3. When you say: *"var iframeContext = iframe.document || iframe.contentWindow.document"* -- is this actual "OR" code, or pseudocode indicating my choice of which to use?
nesting season
ISSUE 4. Your *"top.document.myFunction = function()"* code looks very interesting but I'm getting a parse error.
nesting season
|| is indeed 'OR', which is not exclusive for boolean expressions ;) I clarified my awnser, the parse error was due to a typo (period instead of semicolon). Also removed .document references, we need to target the window (global) object ;)
BGerrissen
nesting season