125

I got a piece of code for javascript which I just do not understand:

function dmy(d) {
    function pad2(n) {
        return (n < 10) ? '0' + n : n;
    }

    return pad2(d.getUTCDate()) + '/' +
       pad2(d.getUTCMonth() + 1) + '/' +
       d.getUTCFullYear();
}

function outerFunc(base) {
    var punc = "!";

    //inner function
    function returnString(ext) {
       return base + ext + punc;
    }

    return returnString;
}

How can a function be defined within another function? Can we call pad2() from outside of my() function?

Please put some light on it. Thanks

2
  • 14
    functions can be created inside of functions. That is perfectly valid. Commented Sep 3, 2011 at 20:22
  • For more info on nested fucntions, see wikipedia Commented Nov 20, 2020 at 13:45

8 Answers 8

166

Functions are another type of variable in JavaScript (with some nuances of course). Creating a function within another function changes the scope of the function in the same way it would change the scope of a variable. This is especially important for use with closures to reduce total global namespace pollution.

The functions defined within another function won't be accessible outside the function unless they have been attached to an object that is accessible outside the function:

function foo(doBar)
{
  function bar()
  {
    console.log( 'bar' );
  }

  function baz()
  {
    console.log( 'baz' );
  }

  window.baz = baz;
  if ( doBar ) bar();
}

In this example, the baz function will be available for use after the foo function has been run, as it's overridden window.baz. The bar function will not be available to any context other than scopes contained within the foo function.

as a different example:

function Fizz(qux)
{
  this.buzz = function(){
    console.log( qux );
  };
}

The Fizz function is designed as a constructor so that, when run, it assigns a buzz function to the newly created object. That is, you'd use it like this:

const obj = new Fizz();
obj.buzz();

or more concisely (if you don't need to keep the object after calling buzz):

new Fizz().buzz();
Sign up to request clarification or add additional context in comments.

5 Comments

What is window.baz = baz? Why does this line m?ke baz available?
@ZiyangZhang, the paragraph after that code block has the explanation, was there a particular part that is unclear?
Perhaps this does different things depending on 'strict'?
Does JavaScript have to recreate "bar" and "baz" every time you call "foo?"
@ZiyangZhang window is a global variable so its properties, including baz in the example above, are available everywhere. See developer.mozilla.org/en-US/docs/Web/API/Window
43

It is called closure.

Basically, the function defined within other function is accessible only within this function. But may be passed as a result and then this result may be called.

It is a very powerful feature. You can see more explanation here:

javascript_closures_for_dummies.html mirror on Archive.org

Comments

15
function x() {}

is equivalent (or very similar) to

var x = function() {}

unless I'm mistaken.

So there is nothing funny going on.

4 Comments

The first syntax will be moved to the start of the document. so it is possible to call function 'x' before the funtion is initialized.
The first syntax will also get you much nicer stack traces with named functions, the second will give you a headache
@TheZ I think Chrome recently added function name inference to debugging so you don't get the same headache as before in the common case.
Lots of funny things are going on. Any variables used in an inner function are captured as snapshots. I think. And maybe referenced global variables are also captured.
10

Function-instantiation is allowed inside and outside of functions. Inside those functions, just like variables, the nested functions are local and therefore cannot be obtained from the outside scope.

function foo() {
    function bar() {
        return 1;
    }
    return bar();
}

foo manipulates bar within itself. bar cannot be touched from the outer scope unless it is defined in the outer scope.

So this will not work:

function foo() {
    function bar() {
        return 1;
    }
}

bar(); // throws error: bar is not defined

Comments

4

When you declare a function within a function, the inner functions are only available in the scope in which they are declared, or in your case, the pad2 can only be called in the dmy scope.

All the variables existing in dmy are visible in pad2, but it doesn't happen the other way around :D

Comments

3

It's perfectly normal in JavaScript (and many languages) to have functions inside functions.

Take the time to learn the language, don't use it on the basis that it's similar to what you already know. I'd suggest watching Douglas Crockford's series of YUI presentations on JavaScript, with special focus on Act III: Function the Ultimate (link to video download, slides, and transcript)

2 Comments

The link no longer works. Could you please update with actual examples?
2

function foo() {
  function bar() {
    return 1;
  }
}
bar();

Will throw an error. Since bar is defined inside foo, bar will only be accessible inside foo.
To use bar you need to run it inside foo.

function foo() {
  function bar() {
    return 1;
  }
  bar();
}

Comments

0

Nested functions can be the basis for writing a modular group of related functions, kind of halfway to full object-oriented programming (static classes only).

Here is an example of such a group of functions, in this case to convert a value to a JSON string or a JSON string to a value.

Notice how the inner functions are grouped into an Object inside an outer function, and how the Object is then stored into a group name. This is the only name directly visible from outside the group. To reach any contained function from outside, you just write the group name, a period, then the function name. To reach a contained function from inside, you can use the same notation, or 'this', a period, then the function name.

//--------------------------------------------------------------------//
//      Module J:
//          Convert from and to JSON strings
//--------------------------------------------------------------------//
const J=NewJ();
function NewJ()
    {
    const mod=
        {
        From:(str)=>
            {
            return JSON.parse(str);
            }, // From
        To:(val)=>
            {
            return JSON.stringify(val,null,3);
            } // To
        }; // mod
    return mod;
    } // NewJ

//--------------------------------------------------------------------//
//      End Module J
//--------------------------------------------------------------------//

Here's a test:

console.log(J.To({A:'a'}));

Console output:

{
   "A": "a"
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.