The Now Platform® Washington DC release is live. Watch now!

Help
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
SlightlyLoony
Tera Contributor

find_real_file.pngYou may sometimes find yourself writing code over and over again with only minor variations. The pattern of these blocks of code (often a function) is the same, but some small particulars may vary. The brute-force approach is to simply bite the bullet and write separate functions to handle each variation, as in this (unreasonably) simple example where we write functions to return particular powers of a number:


gs.log('The square of 5 is: ' + square(5));
gs.log('The cube of 5 is: ' + cube(5));

function square(n) {
return Math.pow(n, 2);
}

function cube(n) {
return Math.pow(n, 3);
}

There's another way to do this sort of thing in JavaScript — in effect, a way to compose functions by using closures and a factory function. Here's the example above, reworked to use this technique:


var square = makePowerFunction(2);
var cube = makePowerFunction(3);

gs.log('The square of 5 is: ' + square(5));
gs.log('The cube of 5 is: ' + cube(5));


function makePowerFunction(exp) {
var e = exp;
return pow;

function pow(n) {
return Math.pow(n, e);
}
}

If you've never run into closures before, this code may make your head explode (especially when you try it and discover that it actually works). Here's the bit of magic that's happening under the covers: when makePowerFunction() returns pow(), it's also returning the complete context that pow() was operating in at the time its value was returned. So when we execute makePowerFunction(2), the "2" is assigned to the variable "e", and then when the function pow() is returned, that value is in its context. Then later in the code when it executes square(5), that context is still being held (in the "square") variable that holds that particular version of the "pow()". The same sort of thing happens with the variable "cube", except that in that case the value is "3".

I'm about to hit you with a more complex example, so stare at that code and think about it until it makes sense. It may help to repeatedly smack yourself on the head with a hard object...

So here's a slightly more realistic example of where you might want to use this approach. A pattern you may see frequently in your JavaScript code is that you need to query a particular table for records where a given field matches a given value. Here's a factory function for such a situation and a couple examples of its use:

var queryUser = queryFactory('sys_user', 'name');
var queryComputer = queryFactory('cmdb_ci_computer', 'name');

var x = queryUser('SlightlyLoony');
gs.log('Have user SlightlyLoony: ' + x.next());

var y = queryComputer('sandb01');
if (y.next())
gs.log('Computer sandb01 is at IP: ' + y.ip_address);

function queryFactory(table, field) {
var t = table;
var f = field;
return query;

function query(value) {
var gr = new GlideRecord(t);
gr.addQuery(f, value);
gr.query();
return gr;
}
}

Now we've got a somewhat more complex query() function, but outside of the queryFactory() function the code is very simple. The first two lines use the queryFactory to make a couple of handy query functions, then we use those query functions to get the information we want. That code is considerably simpler than what we'd have if we repeated the code in the query() function for each use we made of it.

This feature (closures) can be quite a good way to simplify your JavaScript code, if you use it prudently. One specific thing I'd recommend is that you be very careful that your factory function names indicate what's going on. Putting "factory" in the name is a simple way to do this...

1 Comment