Thanks for the kind words. I’ll try to address several questions in this single post.
Debugging JXA
That’s a sore point. There is no JXA debugger per se, the guys from LateNight Software abandoned their project afaik. There are, however, some other possibilities
- check the Apple Events in the Script Editor’s protocol
- poor man debugging with
console.log()
. That writes to the Script Editor’s protocol if the script is running there or to the terminal if it’s running in osascript
.
- Put a
debugger;
line in your script at the place where you want debugging to start. Sounds like magic, but does only start Safari with its web developer tools open at the line following this statement. I guess that you’ll have to turn on Safari’s developer tools for that (Preferences, last tab to the right, “turn on developer menu”).
The latter method is a bit quirky in that it sometimes works as advertised and sometimes not. Also, it does not give you any information about JXA objects. So it helps with standard JS code, but not really with the intricacies of JXA. But it’s better than nothing, I guess
Scope of JS variables … aka
why addCustomMetaData
does not work in your script as you think it should.
Which is a good thing, too Let’s get back to the point where rawAmount
is defined:
function handleRogers(key, r, txt) {
...
const rawAmount = txt.match(/(\d+\.\d\d).../);
// and a bit later
resultObj.amount = rawAmount[1];
So, the first line says that rawAmount
is a const
. Which not only means that its value is not suppsed to change after it has been defined (i.e. after this very line). It also means that rawAmount
is “block local”. A block is, loosely spoken, everything limited by curly braces {}
. Here, the nearest open curly brace is the one after the function definition for handleRogers
. Long story short: rawAmount
is known inside this function, but not outside.
But there’s good news, too. The last line quoted above assigns the first element of this local variable rawAmount
to the property amount
of the object resultObj
. Which is the return value of the function handleRogers
.
If you look at the function processRecord()
, you’ll see that it calls the handler
function and stores its result in its own block-local variable result
(well, one could think of a better name ;-). It is already used here to build the name of the record:
const name = ["company", "subject", "date" ].map(x => result[x]).join('_');
(one of the more obscure ways to write JavaScript code, and I’m aware that I wrote it).
So, instead of using rawAmount[1]
in your call to addCustomMetaData()
, you’d use result.amount
(or result[“amount”] if you prefer that notation).
var
vs. let
vs. const
In the olden days, fortunately long gone, nobody bothered to declare variables in JavaScript. Very much like in Basic, Fortran, Lisp and of course AppleScript, one would just write me = "myself"
and some lines later probably me = "you"
. Or, worse Me = "you"
. Quite obviously a typo, but one that did go unnoticed until the code went havoc.
So var
was introduced as a means to say “Hey, I have a variable with a certain name that I want to stick to” and use strict;
as a means to tell the JavaScript engine that every variable should be declared. So, you’d have to write var me ="myself";
, and using Me = "you";
would cause the JS engine to sputter about an “Unknown variable ‘Me’”. Just as you saw in your code with rawAmount[1]
.
But every var
is global. If you declared a variable inside a function, every other function could see it. And modify it – horribile dictu. Global variables are personae non gratae since ages, so JavaScript introduced let
. Which does just the same as var
, namely declare a variable with a certain name. But let
limits its scope to the current block (think “curly braces”). So, code outside this block has no idea about this variable and cannot involuntarily modify it. Only code inside the block can see and consequently modify these variables. Which is good.
Why would one need const
? Well, there are many values (some would say most of them) in a program that never change. Or never should change, not even accidentally. Therefore, you should use const
to declare a variable (which no longer is variable, but well…) that must never change its value. In all other respects, it works like let
, i.e. the variable is block-local.
There will be a lot more about that to be found online, including examples. As usual, I suggest the excellent Mozilla Developer Network to get a more detailed explanation.