1

I've witnessed the behavior in action and later discovered the concept of "name inference" for anonymous functions (most notably the new arrow functions) but I haven't been able to find where this behavior is defined. For reference:

// Arrow functions are inherently anonymous so this shouldn't work
const foo = () => {};
console.log(foo.name); // outputs "foo"
const bar = function() {};
console.log(bar.name); // outputs "bar"

// vs

console.log((() => {}).name) // outputs ""
console.log((function() {}).name) // outputs ""

The closest thing I've found is on MDN which attributes it to "new in ECMAScript 2015". I tried to search the ES2015 spec with no luck. This seems to be a largely unknown but useful capability of modern ES for which little documentation actually exists.

Can anyone provide a reference to the canonical spec for this?

webbower
  • 756
  • 1
  • 7
  • 21
  • 2
    related: [How do I write a named arrow function in ES2015?](https://stackoverflow.com/questions/27977525/how-do-i-write-a-named-arrow-function-in-es2015) – ASDFGerte Nov 21 '19 at 20:19
  • 1
    https://www.ecma-international.org/ecma-262/6.0/#sec-object-initializer-runtime-semantics-propertydefinitionevaluation Under 12.14.4.1.e.iii among others. Just search that spec for `SetFunctionName` and you're sure to find a lot. – IceMetalPunk Nov 21 '19 at 20:26

3 Answers3

6

Under Function Objects you'll find the name property.

A contextual name is assigned to that property using the SetFunctionName abstract operation, and that is called at various places in the specification:

1) At property declarations inside object literals ({ a: b } sets the name of b to a, if b is an anonymous function).

2) At assignments, (a = b sets b's name to a if a is directly an identifier and b is an anonymous function too).

3) Inside object destructuring default values ({ a = b } = sets bs name to a if b is an anonymous function).

4) inside function parameter destructuring similarily to 3).

5) at variable declarations similarily to 2) (let a = b; const a = b; var a = b;).

6) at function declarations (including generator functions (function a() { }).

7) at object methods, getters (prefixed with "get") and setters (prefixed with "set") ({ a() { }, get a() {}, set a() {} }).

8) at class declarations and expressions (class a {}).

9) When binding functions, the bound function takes over the name of the function to bind prefixed with "bound".

Note that no name is assigned in case that there are computed keys or object property assignments due to security concerns.

Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
  • That section doesn't explain the name inference behavior. It says "Anonymous functions objects that do not have a contextual name associated with them by this specification do not have a name own property but inherit the name property of %FunctionPrototype%." but that just says that it inherits from `Function.prototype.name` which is `""` – webbower Nov 21 '19 at 20:22
  • But a contextual name is usually associated to them – Jonas Wilms Nov 21 '19 at 20:24
1

The function's .name property is created in the SetFunctionName procedure which is called in various places all over the spec, in general when you assign a variable or define a property and the right hand side is an anonymous function expression.

See also ECMAScript 6's function.name property, Definition of name property in assignment expression and Why does `obj.foo = function() { };` not assign the name `foo` to the function? for more discussion.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
0

@asdfgerte for the win (initially) (I don't think I can award a comment as the answer). Found in spec-speak but not named "name inference" http://www.ecma-international.org/ecma-262/6.0/index.html#sec-assignment-operators-runtime-semantics-evaluation

webbower
  • 756
  • 1
  • 7
  • 21