I’ve reading Reg Braithwaite’s JavaScript Allonge, which is great, but in reading it I discovered one of the ways JS is batshit crazy.
We’re all used to writing and calling named functions;
function iAmAvailable() { console.log("iAmAvailable has been called"); } iAmAvailable();
Which gives the nice predictable result;
iAmAvailable has been called
So far so good. And we know we can put a function expression into a variable;
var iPointToAFunction = function() { console.log("iPointToAFunction has been called"); } iPointToAFunction();
And this gives what you would expect, too;
iPointToAFunction has been called
So far, no surprises. But what if you try both together? A function with a name assigned to a variable?
var iPointToAFunction = function butIAmUnavailable() { console.log("iPointToAFunction/butIAmUnavailable has been called"); } iPointToAFunction(); butIAmUnavailable();
This gives the surprising result;
iPointToAFunction/butIAmUnavailable has been called ReferenceError: butIAmUnavailable is not defined at repl:1:1 at REPLServer.defaultEval (repl.js:132:27) at bound (domain.js:254:14) at REPLServer.runBound [as eval] (domain.js:267:12) at REPLServer. (repl.js:279:12) at REPLServer.emit (events.js:107:17) at REPLServer.Interface._onLine (readline.js:214:10) at REPLServer.Interface._line (readline.js:553:8) at REPLServer.Interface._ttyWrite (readline.js:830:14) at ReadStream.onkeypress (readline.js:109:10)
Which is really inconsistent. It seems that because the function has been assigned to a variable, it’s been excluded from the environment. Or maybe it’s the other way around; functions not assigned to variables automatically create a variable of the same name.
Either way, it feels to me that creating a function with a function expression should be more consistent — the grammar like
function x() { ... }
Should either create a function variable called x, or not create it, but not create it ‘only sometimes’, depending on whether you assign it.
This syntax exists so that you can recurse into an anonymous function. When you write:
addEventListener(‘whatever’, function x(){ x(); })
“x” is defined within the scope of the function, but not in the containing scope. This is useful sometimes. Rarely, but sometimes.