5 ms·
They can’t be named in the same standalone way that non-arrow function expressions can, but they do acquire names in some positions that get used in stack trace
by minitech 7y ago
They can’t be named in the same standalone way that non-arrow function expressions can, but they do acquire names in some positions that get used in stack traces and profiles.
> ({ literalProperty: () => {} }).literalProperty.name
'literalProperty'
> ({ ['computedName']: () => {} }).computedName.name
'computedName'
> const variable = () => {};
> variable.name
'variable'
So if you want to name an arrow function, you can usually assign it to a variable.
- austincheney 7y agoThat is three examples of assignments. The arrow functions remain anonymous. * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe... * https://developer.mozilla.org/id/docs/Web/JavaScript/Reference/Functions/Arrow_functions https://developer.mozilla.org/id/docs/Web/JavaScript/Referen...
- roblabla 7y agoYour parent specifically talked about giving it a name in thte stack frame. And assigning an anonymous function to a constant/object and using it through that assignment will cause the stack trace to show a name.
- austincheney 7y agoThe only way to arbitrarily generate a JavaScript stack trace without an error, in both modern browsers and Node, is the following code sample. In order to prove the output of a stack trace you need logic that actually produces a stack trace. new Error().stack The following demonstrations take the prior examples and put the stack call into the arrow function bodies and wrap that in an arbitrary function for an additional line in the stack trace output. The first example assigns the arrow function to an object property. And then generates the name of the object's property name. This does nothing to describe the function. Here is a better example: var stack,a=function(){({ myProperty: () => {stack = new Error().stack;} }).myProperty();};a();stack; In the browser that outputs: "myProperty@debugger eval code:1:59 a@debugger eval code:1:82 @debugger eval code:1:102 Its a bit more clear in Node's REPL 'Error\n' + ' at Object.myProperty (repl:1:59)\n' + ' at a (repl:1:82)\n' + ' at repl:1:102\n' + ' at Script.runInThisContext (vm.js:120:20)\n' + ' at REPLServer.defaultEval (repl.js:432:29)\n' + ' at bound (domain.js:429:14)\n' + ' at REPLServer.runBound [as eval] (domain.js:442:12)\n' + ' at REPLServer.onLine (repl.js:759:10)\n' + ' at REPLServer.emit (events.js:333:22)\n' + ' at REPLServer.EventEmitter.emit (domain.js:485:12)' Essentially the stack traces represent a method call as designated by a function whose identity is bound to an object property, but the function itself remains unnamed. The second example is logically identical to the first except for the minor syntax difference of array notation versus a word type variable name. The third example is logically different than the prior two examples: var stack,a=function(){var myVariable = () => {stack = new Error().stack;};myVariable();};a();stack; Browser: "myVariable@debugger eval code:1:51 a@debugger eval code:1:71 @debugger eval code:1:81 Node: 'Error\n' + ' at myVariable (repl:1:51)\n' + ' at a (repl:1:71)\n' + ' at repl:1:81\n' + ' at Script.runInThisContext (vm.js:120:20)\n' + ' at REPLServer.defaultEval (repl.js:432:29)\n' + ' at bound (domain.js:429:14)\n' + ' at REPLServer.runBound [as eval] (domain.js:442:12)\n' + ' at REPLServer.onLine (repl.js:759:10)\n' + ' at REPLServer.emit (events.js:333:22)\n' + ' at REPLServer.EventEmitter.emit (domain.js:485:12)' The output of assigning an arrow function is identical, in both environments, to assigning a regular anonymous function: var stack,a=function(){var myVariable = function () {stack = new Error().stack;};myVariable();};a();stack; That is different than assigning to a named function: var stack,a=function(){var myVariable = function myFunctionName() {stack = new Error().stack;};myVariable();};a();stack; 'Error\n' + ' at myFunctionName (repl:1:76)\n' + ' at a (repl:1:96)\n' + ' at repl:1:111\n' + ' at Script.runInThisContext (vm.js:120:20)\n' + ' at REPLServer.defaultEval (repl.js:432:29)\n' + ' at bound (domain.js:429:14)\n' + ' at REPLServer.runBound [as eval] (domain.js:442:12)\n' + ' at REPLServer.onLine (repl.js:759:10)\n' + ' at REPLServer.emit (events.js:333:22)\n' + ' at REPLServer.EventEmitter.emit (domain.js:485:12)' And both of those are different to anonymous functions not assigned to a variable. Both of the following examples produce the same output: var stack,a=function(){(function () {stack = new Error().stack;}());};a();stack; var stack,a=function(){() => {stack = new Error().stack;};};a();stack; 'Error\n' + ' at repl:1:46\n' + ' at a (repl:1:65)\n' + ' at repl:1:71\n' + ' at Script.runInThisContext (vm.js:120:20)\n' + ' at REPLServer.defaultEval (repl.js:432:29)\n' + ' at bound (domain.js:429:14)\n' + ' at REPLServer.runBound [as eval] (domain.js:442:12)\n' + ' at REPLServer.onLine (repl.js:759:10)\n' + ' at REPLServer.emit (events.js:333:22)\n' + ' at REPLServer.EventEmitter.emit (domain.js:485:12)' You can see in the first anonymous function example that an IIFE (immediately invoked function expression) is used. Function's require identity, aside from 3 exceptions, otherwise they throw an error. The three exceptions are arrow functions, IIFE, and function arguments. So much of this discussion is nonsense though, because it doesn't make sense to arbitrarily complicate your code with unnecessary objects merely to provide your anonymous arrow functions with identity. The whole point of arrow functions is to reduce syntax and thereby provide easier to read code, which only the third of those three examples provide. It is also helpful to understand that a function's name is an identity known to the function, which means it is available to the internal logic of the function as a local reference and not a scoped reference. The identity of a variable name to which a function is assigned will always be a scoped reference, and that distinction also results in different output in stack traces. Furthermore, none of those examples demonstrates the most important use case, callbacks, or functions as arguments to event handlers. In Node the callbacks become nested very quickly and often times many layers deep. Each use of an arrow function is an anonymous line in the call stack and several layers of anonymous calls is less helpful to read. It's not hopeless because the stack trace provides the location of each call, but you have to dive into the code on each line mentioned to see what is actually happening instead of just reading the function names from a more helpful stack trace.
- minitech 7y agoThis seems like a very verbose retread. What I was saying is if you are currently using a named function: function foo(bar) { // … } you don’t lose the name by making it an arrow function: const foo = bar => { // … }; and yes, you can name your callbacks and event handlers like this before passing them to functions. Introducing variables to name values (any values, not just functions) doesn’t really complicate code. Many times, it can be a readability improvement.