-1

I am developing an MVC app. Up until now I wrote the whole JS code into the views. This is against good practices. Now i am trying to move a part of the code to separate files and then include it into the views. This is code sample:

var scripts = function() {
  var _foo = function foo(){
    // ...
  }

  return {
    init: function () {
      _foo ();
    }
  };
}();

jQuery(document).ready(function() {
  scripts.init();
});

This is what my .js file looks like and works as well. But if I want to define function with parameters as follow:

var scripts = function() {
  var _foo = function foo(params) {
    // ...
  }

  return {
    init: function () {
      _foo ();
      _foo ;
    }
  };
}();

I receive an error in console 'The _foo is not defined' on firing the function. Is there a way just to define the function and use it when it is needed?

Tomas Langkaas
  • 4,551
  • 2
  • 19
  • 34
S.K.
  • 163
  • 3
  • 9
  • 4
    What a title - _How to Do?_. Describes _nothing_. Impressive. – random_user_name Feb 02 '18 at 15:36
  • 2
    What is the purpose of the `_foo;` after the `_foo()` call and why you are not calling it with some parameter as it's defined above? `_foo()` and `_foo(param)` doesn't look the same functions from the example. – Dimitar Feb 02 '18 at 15:37

3 Answers3

1

I receive an error in console 'The _foo is not defined' on firing the function.

It is unclear what you mean here. In the code below, _foo is a local variable within the anonymous function that assigns the object with init: function(){ ... to the scripts variable. Thus, by calling scripts.init(), _foo is accessible and called, as demonstrated below.

But, if you call _foo() directly, it is not defined and accessible in the global scope (since it is a private local variable in the anonymous function).

var scripts = function() {
  var _foo = function foo(params) {
    // ...
    console.log('_foo called');
  }

  return {
    init: function () {
      _foo ();
    }
  };
}();

scripts.init();
_foo(); // will not work, as it is not accessible in global scope

Is there a way just to define the function and use it when it is needed?

Sure, you can make it accessible as a method of the scripts variable, like this:

var scripts = function() {
  var _foo = function foo(params) {
    // ...
    console.log('_foo called with ' + (params ? '' : 'no ') + 'params.');
  }

  return {
    init: function () {
      _foo ();
    },
    _foo: _foo // make _foo accessible on scripts
  };
}();

scripts.init();
scripts._foo('a parameter');
Tomas Langkaas
  • 4,551
  • 2
  • 19
  • 34
0

There are several ways to do functions within an object. As an alternative to your "scripts" object, Here I use the prototype and the makeClassStrict (from another question on this site) here https://stackoverflow.com/a/17588082/125981)

This creates an object called "MyClass" to which I may add functions such as here my newFoo function with parameters. I also illustrate the init function concept you have in your post which allows me to pass parameters to the init simply at time of instance creation by simply passing paramters to my MyClass() as var newInstanceThing = MyClass("fred"); for example.

Note also I added a function called origFoo

/* JavaScript makeClass example */
/* http://ejohn.org/blog/simple-class-instantiation/ */
// makeClassStrict - By Hubert Kauker 
// original by John Resig (MIT Licensed).
function makeClassStrict() {
  var isInternal, instance;

  var constructor = function(args) {
    // Find out whether constructor was called with 'new' operator.
    if (this instanceof constructor) {
      // When an 'init' method exists, apply it to the context object.
      if (typeof this.init == "function") {
        // Ask private flag whether we did the calling ourselves.
        this.init.apply(this, isInternal ? args : arguments);
      }
    } else {
      // We have an ordinary function call.

      // Set private flag to signal internal instance creation.
      isInternal = true;
      instance = new constructor(arguments);
      isInternal = false;
      return instance;
    }
  };

  return constructor;
}
var MyClass = makeClassStrict(); // create object
MyClass.prototype = {
  origFoo: function(mything) {
    return mything;
  }
}
//  add init to my new "MyClass" prototype, could be in object above also
MyClass.prototype.init = function(newText, newThing) {
  this.someText = newText == undefined ? 'defaultText' : newText;
  this.newThing = newThing == undefined ? 'defaultThing' : newThing;
  this.gobble = 'turkey';
  this.cracker = 'cheese';
}
// add a new function newFoo
MyClass.prototype.newFoo = function(foome, foometwice) {
  this.foo = foome;
  this.foo2 = foometwice;
}
// add a new string object to the prototype
MyClass.prototype.otherText = 'otherstuff';

// create instance of my class with parameter for newText
var trustme = MyClass('trustmedude'); // init gets used
console.log(trustme.someText + ":" + trustme.newThing);
console.log(trustme.origFoo("wilber was here"));

// create instance with parameter for newText and newThing
var iam = MyClass('some new text', 'mything');
console.log(trustme.newThing); // logs defaultThing
console.log(iam.someText); //logs "some new text"
iam.someText = 'hi fred'; // change it for this instance
console.log(iam.someText); //logs "hi fred"
console.log(iam.otherText); // logs "otherstuff" set above
console.log(iam.newThing); //logs "mything"
// note don't use the prototype directly
console.log(MyClass.someText); //logs undefined
console.log(MyClass.otherText); //logs undefined
// these are in the instance
console.log(iam.cracker + iam.gobble); //logs "cheeseturkey"
console.log(iam.hasOwnProperty("someText")); //logs true
// show that they ARE different in each instance
console.log(iam.gobble + ":" + trustme.gobble + ":" + trustme.someText + ":" + iam.someText);
// do our foo function and properties stuff
iam.newFoo("fooby", 123);
console.log(iam.foo, iam.foo2);
Mark Schultheiss
  • 32,614
  • 12
  • 69
  • 100
0

Thank you all for the answers. Take me some time to get back here, but I have a solution that's suits me. I will explain my self little more before paste a code solution. The case was that I needed a function that accept params but I want to use it when it is time. For example if you have javascript function that accept html element like 'input type=file' and you want on change event on this html element to pass it to this function. I hope the example was clear enough.This is a simple example of code what I was looking for:

var Scripts = function(){
  var _example =function(params){
    code.....
  };
  return {
     init:function(){
      ...call some other functions.....
     },
     example:_example 
  }

}();
jQuery(document).ready(function(){
  Scripts.init();
})



Scripts.example(params);...call function like this in tour code...
S.K.
  • 163
  • 3
  • 9