Passing optional variables to internal function calls. Or something like that

Hello,

I’m a novice at JS, and I’m trying to organise my app with a module kind of system but can’t seem to figure something out. In the example below, I define modules in the app.modules object and those get auto run by app.init(). I’m trying to pass app.settings and app.utils to those functions and achieve it in the following code, however the order has to be the same as those that I pass to it. So I couldn’t just use utils if I didn’t want settings. I’m trying to make them optional, so that if I only need one, I can ask for it and don’t get passed the others. Kind of like how you can pass things to angular controllers if and when you need them.

I hope that explains it well enough, I struggled at the title. And the example below is a simplified version, there could be more vars like settings and other objects like app.utils.

var app = (function($){

	var settings = {
		option1: 1,
		option2: 2,
		etc: 'etc...'
	}

	return {
		init: function(){
			for (var prop in this.modules) {
				if ( this.modules.hasOwnProperty(prop) ) {
					this.modules[prop].call(null, settings, this.utils);
				} 
			}
		}
	}

})(jQuery);

app.utils = {
	getSomething: function(option){
		return option;
	},
	getSomethingElse: function(option){
		return option;
	}
}


app.modules = {
	runthis: function(settings, utils) {
		console.log(settings);
	},
}

Appreciate any advice, thanks!

Angular dependencies work like this:

app.module(['settings', 'utils'], function(settings, utils) {
  console.log(settings);
  console.log(utils);
})

By providing an array of the things you want to include you can use apply rather than call when running this function with the right arguments.

I’d use a proper module system like Browserify though, each module can be in it’s own file and import / export what it needs. http://www.sitepoint.com/javascript-modules-bundling-transpiling/

CommonJS modules:

var settings = require('./settings');
var utils = require('./utils');

module.exports = function() {
  console.log(settings);
  console.log(utils);
}

es6 modules

import settings from './settings';
import utils from './utils';

export default function() {
  console.log(settings);
  console.log(utils);
}

Other module patterns without using a proper bundler are pretty hacky.

Hi mark,

Whilst I do agree the use of a module loader system would be the best option, I suppose I was primarily asking how to accomplish the above, like what angular does as you’ve mentioned.

I could of, I guess, asked simply how the .module() function works, because although it’s similar to apply I don’t think it works quite the same way. At least to what I’ve done, or as I’m understanding. If the above code was written as:

app.module(['utils'], function( utils) {
   console.log(settings);
   console.log(utils);
});

Then utils would still work, and settings would be undefined I think, wouldn’t it? Whereas in my code, utils would now be a reference to the passed in settings variable (and settings would still be undefined).

I tried to look in the source of angular, but couldn’t for the life of me find where it was defined…

Hope that makes sense, and thanks for the link, nice read.

Cheers.

Here’s an approach to what you’re describing:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title></title>
</head>
<body>
<script type="text/javascript">

var app = (function() {

  var modules = {};

  return {
    module: function(name, obj) {
      modules[name] = obj;
    },
    run: function(deps, fn) {
      deps = deps.map(function(dep) {
        return modules[dep];
      });

      fn.apply(null, deps);
    }
  }

})();

app.module('settings', {
  option1: 1,
  option2: 2,
  etc: 'etc...'
});

app.module('utils', {
  getSomething: function(option){
    return option;
  },
  getSomethingElse: function(option){
    return option;
  }
})

app.run(['settings', 'utils'], function(settings, utils) {
  console.log(settings);
  console.log(utils);
});

app.run(['utils'], function(utils) {
  console.log(utils);
});

</script>
</body>
</html>

This will work but has a problem that everything needs to be in a specific order for it to work, and your modules can’t require other modules. This should give you an idea of how this type of thing is done though.

I could of, I guess, asked simply how the .module() function works, because although it’s similar to apply I don’t think it works quite the same way.

When you use call you need to know all of the arguments, apply lets you use an array of arguments so can be used for a dynamic number of arguments here.

1 Like

That’s a brill reply Mark, very helpful and answered my question :slight_smile:

Although you raise some valid points, at least I’ll have a starting point now.

Thanks for the help!

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.