51

I have the following piece of code:

function initValidation()
{
    // irrelevant code here
    function validate(_block){
        // code here
    }
}

Is there any way I can call the validate() function outside the initValidation() function? I've tried calling validate() but I think it's only visible inside the parent function.

Eduard Luca
  • 6,514
  • 16
  • 85
  • 137
  • When it comes to functions, anything between the curly braces is inaccessible to the outside unless made accessible, such as through dot notation property assignment or the return statement. You can do the assignment outside or inside the outer function, but either way it requires an outside action, the minimum being to run the outer function once. – Magnus Lind Oxlund Jun 02 '19 at 12:21

11 Answers11

126

    function initValidation()
    {
        // irrelevant code here
        function validate(_block){
            console.log( "test", _block );
        }
    
        initValidation.validate = validate;
    }

    initValidation();
    initValidation.validate( "hello" );
    //test hello
Arun Prasad E S
  • 9,489
  • 8
  • 74
  • 87
Esailija
  • 138,174
  • 23
  • 272
  • 326
  • 11
    I think this answer is the one that really answers the question. Thanks! – Antony Harder Feb 12 '14 at 15:32
  • For some reason, I had not seen this answer at that time. I've updated it as the accepted answer, since it's clearly the best way to go. – Eduard Luca Jan 30 '17 at 09:33
  • @yuno Please refrain from "code golfing" on others' answers. – Heretic Monkey Jun 14 '17 at 22:13
  • 2
    i am not able to get why are we calling `initValidation();`. Can someone please help me ? – Harkirat Saluja Feb 28 '18 at 08:22
  • @HarkiratSaluja - Try removing `initValidation()`, you will get an error. Reason is first you need to initialize `initValidation.validate()` by calling `initValidation()`. – lmao Apr 07 '19 at 19:13
  • A tricky problem is relative to this. Can we modify the code so that instead of calling the default nested `validate` we call an external a modified `validate` function that will also be callable from inside the original function `initValidation` ie something like classes that extends the parent and modify its method (polymorphism). Take in mind that we can not change the original function ie `initValidation` – Maverick Nov 08 '22 at 07:32
22

Hope that you are looking for something like this

function initValidation()
{
    // irrelevant code here
    this.validate = function(_block){
        // code here
    }
}

var fCall = new initValidation()
fCall.validate(param);

This will work.

Hope this addresses your problem.

AmGates
  • 2,127
  • 16
  • 29
7

You can call validate from within initValidation. Like this.

function initValidation()
{
    // irrelevant code here
    function validate(_block){
        // code here
    }

    return validate(someVar);
}

validate is not visible to anything outside of initValidation because of its scope.

Edit: Here's my suggestion of a solution.

(function() {
    function validate(_block){
        // code here
    }

    function initValidation()
    {
        // irrelevant code here

        return validate(someVar);
    }

    function otherFunctions() {
        // ...
    }

    // initValidation = function
}());

// initValidation = undefined

All of your functions will be hidden to anything outside the function wrapper but can all see each other.

Olical
  • 39,703
  • 12
  • 54
  • 77
  • If it still is not working try debugging `validate`. Place an `alert` / `console.log` call in it and see if it is executing. – Olical Jan 11 '12 at 10:43
  • Thanks. I wanted to call it from outside `initValidation`, but I see it's not possible. – Eduard Luca Jan 11 '12 at 10:47
  • 3
    No, thats why its nested. Don't nest it if you want to use it outside the initValidation function. – Erik Dekker Jan 11 '12 at 10:49
  • You can try just placing the function outside of `initValidation`. Sure it will be global then but it will still be accessible from `initValidation`. Why not wrap all of your functions in something like `(function() { /* CODE HERE */ }())`. It will stop everything becoming global but allows your functions to see each other. – Olical Jan 11 '12 at 10:50
  • @EduardLuca, if you want to access the function from **outside** its enclosing scope (in your question you said inside, which is the exact opposite) you shouldn't be declaring it inside. That's a design mistake. There are ways around it, but why not just define the function where you need to call it? – davin Jan 11 '12 at 10:50
  • I have just added a solution to my answer which should solve all of your problems. – Olical Jan 11 '12 at 10:53
3

This invocation will return function statement, which is function validate. So you can invoke directly after the first invocation.

function initValidation() {
  // irrelevant code here
  return function validate(_block) {
    // code here
  }
}

initValidation()();
1

I know this is an old post but if you wish to create a set of instances that you wish to work with that reuse the code you could do something like this:

"use strict";
// this is derived from several posts here on SO and ultimately John Resig
function makeClassStrict() {
  var isInternal, instance;
  var constructor = function(args) {
    if (this instanceof constructor) {
      if (typeof this.init == "function") {
        this.init.apply(this, isInternal ? args : arguments);
      }
    } else {
      isInternal = true;
      instance = new constructor(arguments);
      isInternal = false;
      return instance;
    }
  };
  return constructor;
}
var MyClass = makeClassStrict();// create "class"
MyClass.prototype.init = function(employeeName, isWorking) {
  var defaultName = 'notbob';
  this.name = employeeName ? employeeName : defaultName;
  this.working = !!isWorking;
  this.internalValidate = function() {
    return {
      "check": this.working,
      "who": this.name
    };
  };
};
MyClass.prototype.getName = function() {
  return this.name
};
MyClass.prototype.protoValidate = function() {
return {
      "check": this.working,
      "who": this.name
    };
};
var instanceBob = MyClass("Bob", true);// create instance
var instanceFred = MyClass("Fred", false);// create instance
var mything = instanceFred.internalValidate();// call instance function
console.log(mything.check + ":" + mything.who);
var myBobthing = instanceBob.protoValidate();
console.log(myBobthing.check + ":" + myBobthing.who);
Mark Schultheiss
  • 32,614
  • 12
  • 69
  • 100
1

I know this thread's been here for quite some time but I thought I'd also leave my 0.02$ on how to call inner functions from outside their scope (might benefit somebody).

Note that in any place, a better design decision should be taken into consideration rather than some hackish workaround which will bite you back later.

How about using function expressions instead of function statements and making use of the global scope.

      var innerFn;
    
      function outerFn() {
        innerFn = function(number) {
          return number ** 2;
        }
      }
    
      outerFn();
      console.log(innerFn(5));

      // if there's more complex code around and you could write this defensively

      if (typeof innerFn !== 'undefined') {
        console.log(`we are squaring the number 5 and the result is: ${innerFn(5)}`);
      } else {
        console.log('function is undefined');
      }

Or, you can make use of closures:

function outer() {
  // initialize some parameters, do a bunch of stuff
  let x = 5, y = 10;

  function inner() {
    // keeps references alive to all arguments and parameters in all scopes it references
    return `The arithmetic mean of the 2 numbers is: ${(x + y) / 2}`;
  }
  
  return inner;
}

innerFn = outer(); // get a reference to the inner function which you can call from outside
console.log(innerFn());
Marius Mucenicu
  • 1,685
  • 2
  • 16
  • 25
1

Create a variable outside the parent function, then in the parent function store your required function in the variable.

Var Store;
Function blah() {

    Function needed() {
        #
    }

   Store = needed;
}
Tomer Shetah
  • 8,413
  • 7
  • 27
  • 35
Alfred
  • 51
  • 4
0

As a minor variation of Esailija's answer, I did this:

function createTree(somearg) {
    function validate(_block) {
        console.log( "test", _block );
    }
    if (somearg==="validate") { return validate; } // for addNodes

    // normal invocation code here
    validate(somearg);
}

function addNodes() {
    const validate = createTree("validate");
    //...
    validate( "hello" );
}

createTree("create");
addNodes();
//validate("illegal");

so validate() is now perfectly shared between createTree() and addNodes(), and perfectly invisible to the outside world.

Pete Lomax
  • 93
  • 1
  • 8
-1

Function definition:

function initValidation() {
   // code here
   function validate(_block){
     // code here
     console.log(_block);
   }
   return validate;
}

Call it as below:

initValidation()("hello");
kkk
  • 1,850
  • 1
  • 25
  • 45
Shraddha J
  • 714
  • 9
  • 17
-1
function initValidation()
{
   
    function validate(_block){
        console.log(_block)
        // code here
    }
    // you have to call nested function
    validate("Its Work")
}

// call initValidation function
initValidation()
Donald Duck
  • 8,409
  • 22
  • 75
  • 99
  • While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value. – Donald Duck Dec 21 '20 at 16:38
-1

Should work.

function initValudation() {
    validate();
    function validate() {

    }
}
Carl Bergquist
  • 3,894
  • 2
  • 25
  • 42
  • Not ideal - since here the variable 'validate' is used before it's defined. – Daniel Attfield Jan 11 '12 at 10:49
  • 1
    @DanielAttfield, on what basis is that not ideal? It might not be a style you like, but that's purely subjective. – davin Jan 11 '12 at 10:52
  • @davin I'm a big subscriber to Douglas Crockford, using the 'Good Parts' of JavaScript, and using style to make your code better, more maintainable and less error-prone. As a basis, I refer you to this video, which is Crockford discussing style and can answer you much better than I can! http://www.youtube.com/watch?v=taaEzHI9xyY&hd=1 – Daniel Attfield Jan 11 '12 at 10:56
  • @DanielAttfield, my point is that it's worth pointing out that it's a style issue. Semantically it is perfectly valid. – davin Jan 11 '12 at 10:58
  • @davin I don't usually feed the troll, but I'll point out that I said 'not ideal', not 'wrong'. – Daniel Attfield Jan 11 '12 at 10:59
  • @DanielAttfield `not ideal` is ambiguous, @davin was just trying to make sure people knew that your statement is a style preference to you. Not anything to do with actual semantics. – Chad Jan 11 '12 at 20:30
  • This will execute if one calls initValudation(); ence my downvote – Ced Apr 13 '16 at 17:11