0

I'm curious why a named function expression's name property is the value of the function declaration construct's name, rather than the variable that can be used to execute the function.

function functionDeclaration(){
   return;
}

var anonymousFunctionExpression = function(){
   return;
}

var namedFunctionExpression = function functionName(){
  return;
}


console.log(functionDeclaration.name);//As expected, function name is 'functionDeclaration'
console.log(anonymousFunctionExpression.name);//As expected, function name is 'anonymousFunctionExpression'
console.log(namedFunctionExpression.name);//Why is the function's name 'functionName' and not 'namedFunctionExpression?' 
Stu
  • 324
  • 3
  • 10
  • 1
    because you explicitly named the function? In case 1 and case 3, you declared a function _with a name_ so that's what `.name` is going to point to. Case 2 is the surprising one, but [does some name-finding magic as of ES6](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name#Inferred_function_names). – Mike 'Pomax' Kamermans Apr 16 '19 at 22:44
  • 1
    I mean... one *has* to take precedence over the other. Why should the variable name take precedence over the actual name of the function? – Kevin B Apr 16 '19 at 22:47
  • Note in particular [this answer](https://stackoverflow.com/a/36498151/902497) that cites the spec: An assignment operation updates the `name` property only if the function doesn't already have a `name`. – Raymond Chen Apr 16 '19 at 22:50
  • So it seems that the answer is "because that's what the spec says", I'm was wondering the thought process behind defining what gets precedence. – Stu Apr 16 '19 at 22:57
  • 1
    Well it kinda makes sense that an explicit name takes precedence over an infered one. The `name` property is just there to be helpful in debugging which is the only reason the inference is there at all. – Lennholm Apr 16 '19 at 23:01

1 Answers1

-2

That's just how it works. If the function in the function expression is named, that name (on the right of the =) will be used - otherwise, if not named, the .name will give you the variable name the function was assigned to when the function was created. (If it's a function declaration and not a function expression, then the .name is just the name of the declared function.)

Note that if you reassign a function created anonymously, its name remains the original variable name the function was assigned to. This is what's happening in case 2, when the interpreter must infer the variable name:

const fn = () => {};
const fn2 = fn;
console.log(fn.name);
console.log(fn2.name);

In cases 1 and 3, the interpreter does not need to infer the variable name, because the function has an explicit name already when it was defined:

function functionDeclaration(){
    //   ^^^^^^^^^^^^^^^^^^^
   return;
}
// and
var namedFunctionExpression = function functionName(){
    return;                            ^^^^^^^^^^^^
}

The interpreter would only keep track of the namedFunctionExpression if it needs to infer the function name from its creation context (which is an ES2015 feature) - and this inference is only done in case 2.

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320