I just learned that, writing this:
const setName = name => {
// set name here
}
is bad as opposed to this
function setName(name) {
//set name here
}
The reason was that the first approach makes it difficult to debug issues related to that function since it will not appear in the stack trace.
Question: Why would this not appear in the stack trace?
Arrow functions aren't suitable for call , apply and bind methods, which generally rely on establishing a scope. Arrow functions cannot be used as constructors. Arrow functions cannot use yield , within its body.
ES6 introduced a new and shorter way of declaring an anonymous function, which is known as Arrow Functions.
The main difference between anonymous functions and arrow functions in PHP is the use of the use keyword. In order to have access to the scope outside of the anonymous function, you must use the use keyword. Arrow functions automatically have access to scope outside of the function.
Unlike regular functions, arrow functions do not have their own this . The value of this inside an arrow function remains the same throughout the lifecycle of the function and is always bound to the value of this in the closest non-arrow parent function.
Are Arrow Functions Untraceable?
No, they're just as traceable as any other function, if you're referring to being able to debug them, stack traces, etc.
I just learned that, writing this...is bad as opposed to this...
No, it isn't. It's different. It's not objectively bad.ΒΉ
The reason was that the first approach makes it difficult to debug issues related to that function since it will not appear in the stack trace.
Yes it will. If someone told you it won't, they're mistaken π β which is understandable, because arrow functions don't have a declaration syntax, and their expression syntax doesn't have anywhere to put a name; so it seems reasonable to assume they don't get names. While some don't, many, many do (see my answer here for details on how and when), including yours. Let's see the name in a stack trace:
const setName = name => {
throw new Error("Ack!");
};
const wrapper = name => setName(name);
wrapper("foo");
Look in the real console.
If you run that, you'll see this in the console:
Notice how both setName
and wrapper
are listed.
So even functions created with anonymous syntax can (somewhat paradoxically) get names, and often do. This isn't just something that a specific JavaScript engine does to be helpful (though it used to be), it's dictated by the JavaScript specification.
So what is anonymous function syntax vs. named function syntax? Let's quickly review five common ways to create functions (this isn't a full listΒ β I provide one hereΒ β just five common ones):
A function declaration (the ^
markers indicate the declaration itself, the β
markers indicate the contents of the function):
function example1() { return 42; }
// ^^^^^^^^^^^^^^^^^^^^^ββββββββββββ^
A named function expression (relatively rare):
const example = function example2() { return 42; };
// ^^^^^^^^^^^^^^^^^^^^^ββββββββββββ^
An anonymous function
expression:
const example3 = function() { return 42; };
// ^^^^^^^^^^^^ββββββββββββ^
A "verbose" arrow function expression (has a function body block, no implied return
):
const example4 = () => { return 42; };
// ^^^^^^^ββββββββββββ^
A "concise" arrow function expression (no function body block, implied return
):
const example5 = () => 42;
// ^^^^^βββ
function
declarations always include a name (with one obscure exceptionΒ²). function
expressions can be named or anonymous. All arrow function expressions are anonymous. But all of the functions in those examples have names (example1
, example2
, example3
, example4
, and example5
). Their names are assigned based on the expression they're a part of. (See the answer linked earlier for details.)
To be clear: Some arrow functions don't have names, just like some traditional functions don't have names. For instance, neither of these functions has a name:
result = theArray.map(s => s.toUpperCase());
result = theArray.map(function(s) { return s.toUpperCase(); });
The only advantage with regard to names that traditional functions have over arrow functions that their expression syntax lets you specify a name explicitly rather than relying on context, like this:
result = theArray.map(function upperCaseCallback(s) { return s.toUpperCase(); });
There's no way to do that in a single expression with an arrow function, you'd need something like this instead:
const upperCaseCallback = s => s.toUpperCase();
result = theArray.map(upperCaseCallback);
But even though some arrow functions are anonymous, your example isn't.
ΒΉ In fact, there are some arguments the other way: The arrow function doesn't have a prototype
property and an object associated with it, and calling it doesn't require setting up a new this
binding or arguments
pseudo-object and binding (since arrows don't have their own this
, arguments
, or [where relevant] super
). So in theory, it's lighter-weight. Countering that is some question of readabilityΒ β "I didn't realize that was a function" (though I suspect people will get used to arrow functions)Β β and the hoisting behavior of function
declarations is sometimes useful and has no arrow analogue.
Β² "function
declarations always include a name (with one obscure exceptionΒ²)." The obscure exception is this:
export default function() { }
That's an exported function declaration, not a function expression, with hoisting and such. It's the only place a function declaration can have no name specified. (The function does get a name, though: default
.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With