javaScript functions

functions are Objects too.

As I mentioned in Learning javaScript every variable in js is an object. A javaScript function is also an object. This means it can be assigned to a variable.

consider this..
function x() {
    .. do something;
    return anAnswer;
}

did you know you can say this..
var x = function() {
    .. do something;
    return anAnswer;
};

This is what is known as an anonymous function, characterized by function() with no name. 

Not only that, but you can pass a function that you define on the fly as an argument to another. 

This is how to enumerate through the VBA collection object I imitated in javaScript.

  co.forEach ( 
    function(cItem,cIndex) {
        //do what you need to do in here
        Logger.log (cItem + ':index' + cIndex);
    }
  )

Receiving method..
  this.forEach = function(yourFunction) {
    for (var i = 0 ; i < self.count() ; i++ )
     yourFunction( self.item(i+pBase), i+pBase) ; 
  };
What's happening here is that the function defined in the call to .forEach is called for every item in the collection, with the arguments of the item itself along with its index. This enables the continued use of the for each construct in VBA that does not (really) exist in javaScript.

javaScript functions versus VBA procedures

There is a distinction in VBA between a sub (do something, return nothing) and a function ( do something, return something). In javaScript everything is a function, even the function void(0), which will return 'undefined'. You can of course choose to return something or not in your own functions.

There is a distinction in VBA, y = x(a,b) is clearly a function. However a function can be called as if it were a sub - x a,b is legal, but you can't put in the brackets (unless you say Call x(a,b)).

The ability to assign functions to variables is what allows us to create methods of classes (see  classes and javaScript) , even though strictly speaking, classes do not exist in js. 

Consider this..
var cls = function(n) {
    var p = 'private';
    this.name = n;
    this.m1 = function() {
        .. do something;
        return anAnswer;
    };
    this.m2 = x();
    this.m3 = x;
    this.p1 = function () {
        return p;
    };
    this.p2 = p;
};

What's the difference between each of these?

this.m1()  is a method, and will execute the function each time it is referenced.
this.m2 is a property and will execute x() only once when it is initialized.
this.m3() is a method and since we have defined function x() elsewhere it will call x() when referenced
this.p1() is a method that will access the private variable p each time it is referenced.
this.p2 is a property that will contain the value of p as it was when this class was constructed.

Properties or methods?

In VBA, the distinction between reading a property and executing a method that is a function is kinda blurry. When you see code like x = r.value  you don't really know if this a property or a function, and it doesn't really matter, since VBA knows that in each case, you want the .value property/function to be executed and returned right now.

so consider this js;
var c = new cls('ramblings');
alert (c.m1);
alert (c.m1());

We are calling the method m1 as defined in the earlier example. Remembering that a function in js is just an object, in the first case what will be displayed is the source code of the function m1!! and the javaScript interpreter will be quite unaware that this was a stupid thing to be asked to do. The second example will of course execute c.m1() just as VBA would.

This presents very specific challenges when converting code from VBA to javaScript, especially when dealing with classes. 
  • Things that are intuitively properties ( for example this.p1 in our example), have to be treated as methods because of the technique for dealing with private properties, or because they have been defined using the prototype approach (see classes and javaScript). Your VBA code that used to say cls.p1 now need to say cls.p1(); 
  • Once something makes the transition from property to method because of some of the reasons already mentioned, then simply assigning a value to the property, for example cls.value = x, will not work anymore, since cls.value is actually the source of a function, rather than a real property. This means that many writeable properties now need a method to set them - for example cls.setValue(x), where setValue would apply x to the private copy of the value property.
All this is a nightmare for converting code - is it a property that now needs to be a method() ? When you see the approach that Google Apps have taken, you will see that items that are intuitively properties, but that are actually methods, have had their names changed- for example getValue() or setValue(), to emphasize that brackets will be needed. This is a good approach, but if your strategy is to minimize code changes by keeping the same names etc, this can be a problem too. 


For more like this, see  From VBA to Google Apps Script . Why not join our forum,follow the blog or follow me on twitter to ensure you get updates when they are available. Much of  the code referred to here is the mcpher library. You can find out how to include it in your project here.


Transitioning is covered more comprehensively in my my book, Going Gas - from VBA to Apps script, available All formats are available now from O'Reilly,Amazon and all good bookshops. You can also read a preview on O'Reilly.




Comments