A bit of a monologue about various syntax changes and adjustments in learning and using the tool.
Arrow functions are fun and dandy, but there are some serious side effects around, and if you're not aware of them can make debugging very frustrating.
The main gotcha has to do with the behaviour of the this
keyword inside one of these babies. For long-form function myFunction() {}
function, inside the body the this
is referring to itself, which is different from what this
is outside of the function.
For an arrow function, the this
value is the same both inside and outside of it.
Upshot, if you aren't using this
anywhere, you don't need to know much about it, but then you won't be able to use classes.
You have two choices when an arrow function does not have any parameters:
- Empty parentheses
- Use the underscore
_
variable
// empty parentheses:
() => {}
// underscore variable
_ => {}
I prefer the latter, because Javascript has enough parentheses as it is, and it usually hurts my eyes whenever I see it.
And it should be noted that using a single _
is no special meaning in JavaScript: It is actually a legal variable name. In many languages, the _
is used to refer to a placeholder variable that is never used. So in this case, we are actually defining an arrow function with one parameter; it is just never used.
Arrow functions can optionally have a {}
block, in which case you don't have a return statement. But if you return an object, we have a confusing syntax:
_ => {obj: 'obj'}
That looks a lot like a body {}
rather than an object literal. So, you're supposed to use parentheses (told you there are a lot of parentheses) instead:
_ => ({obj: 'obj'})
Sigh.
There is nothing on its own wrong with var
, but I think it's worth "overcompensating" when transitioning to V8 and to exclusively use const
or let
instead for a while, to get the hang of it.
The massive difference between const
/let
and var
is the scope. The former obeys its scoping rules according to the nearest curly braces block, and the latter obeys its scoping rules to the enclosing function.
Any variable made with var
has an additional oddity in that it is "hoisted" -- and odd it is. If you haven't learned what hoisted is referring to but have been scripting happily along without knowing much about it, then that is a case in point to use const
/let
instead.
Whenever you make a variable that will not be reassigned to some value. It is important to understand that if the value itself is an object where assignments make sense (such as objects) you can still use assignment statements on those, just not on the variable immediately after the const
.
Whenever you make a variable that could be reassigned to some value. It doesn't have to be reassigned, but if there is no possibility of it, use const
instead.
There is an interesting pattern that can be used which I quite like. Here's the problem:
function getResponseFromUrl(url) {
try {
const response = UrlFetchApp.fetch(url);
} catch (e) {
Logger.log("Oh no, error");
}
return response; // fails
}
What's the problem? Well, const response
is defined inside the try {}
area, and is used again in the return
statement outside of it. You can't do that, because const
variables obey rules according to the immediate curly braces.
You could do this:
function getResponseFromUrl(url) {
let response;
try {
response = UrlFetchApp.fetch(url);
} catch (e) {
Logger.log("Oh no, error");
}
return response; // fails
}
That's just fine. But I much prefer this method:
function getResponseFromUrl(url) {
const response = (_ =>
return UrlFetchApp.fetch(url);
} catch (e) {
Logger.log("Oh no, error");
}();
return response; // fails
}
What the heck is going on there?
First of all one thing we have is a self-invoking function. You can do that:
(function log (text) {
Logger.log(text);
})("Hello World");
That calls the function log
immediately after being created, with the value "Hello World"
as text
. The arrow function equivalent is:
(text => {
Logger.log(text)
})('Hello World');
Which means we can get around the earlier const
problem by doing this:
const variable = (_ {
return 'value';
})();
Logger.log(variable);
The (_
is confusing at first, but it's actually the _
representing that there is no parameter, with a (
enclosing the function until )
, there it then calls itself with ()
.
Kinda cool.
Great writeup. I think you're missing a
{
infunction getResponseFromUrl(url) {
right after the=>
.