As of ES2015 (ES6), functions have proper names (including an official name
property), and names are assigned when the function is created in a variety of ways in addition to the obvious function declaration and named function expression, such as assigning to variables (function's name is set to the variable's name), assigning to object properties (function's name is set to the property's name), even default values for function parameters (function's name is set to the parameter's name). But assigning to a property on an existing object (e.g., not in an object initializer) doesn't assign that property's name to the function. Why not? Surely there must be a specific reason it was not desirable/possible. What was it?
To be clear: I'm not asking how to work around it. I'm asking what prevents this seemingly-obvious case from being handled when so many others (including default parameter values!) are. There must be a good reason.
Please don't speculate or theorize. TC39 had a reason for not including it. I'm interested in what that reason was. I've been through the TC39 meeting notes but haven't found it yet. The closest I've found so far is Allen Wirfs-Brock replying to Bergi to say there was no consensus for doing it for that form because of "various objections," but sadly he didn't say what those objections were.
Details:
All of the following assign the name foo
to the function on a compliant browser:
// Requires a compliant browser
// Assigning to a variable or constant...
// ...whether in the initializer...
{
let foo = function() { };
console.log("1:", foo.name); // "foo"
}
{
const foo = function() { };
console.log("2:", foo.name); // "foo"
}
// ...or later...
{
let foo;
foo = function() { };
console.log("3:", foo.name); // "foo"
}
// As an initializer for an object property
{
const obj = {
foo: function() { }
};
console.log("4:", obj.foo.name); // "foo"
}
// Or as a method
{
const obj = {
foo() { }
};
console.log("5:", obj.foo.name); // "foo"
}
// Even if it's a computed property name
{
let name = "f";
const obj = {
[name + "o" + "o"]() { }
};
console.log("6:", obj.foo.name); // "foo"
}
// As a default value for a parameter
(function(foo = function() { }) {
console.log("7:", foo.name); // "foo"
})();
// ...and a bunch of others
But assigning to a property on an existing object, outside an object initializer, does not:
const obj = {};
obj.foo = function() { };
console.log("Nope:", obj.foo.name);
As far as I can tell, this is covered by this section of the specification, which explicitly only sets the function name if the IsIdentifierRef of the LeftHandSideExpression is true (which apparently it isn't for property references).
So reiterating from above: Why not? Surely there must be a specific reason it was not desirable/possible. What was it?
foo["2for1"] = function...
is totally valid but "2for1" is not a valid function name....although that would apply equally to the computed example. – Swirly2for1
is a valid function name: jsfiddle.net/Lx825mgf Function names, like property names, don't have to be valid identifiers. :-) (Edit: Heh, just saw your comment edit.) – Vergarafoo.2for1 = function...
andfunction 2for1() {}
both throw, because JS identifiers can't start with numbers. – SwirlyMemberExpression[Expression] = FunctionExpression
. – Swirlyobj.prop1 = obj.prop2 = function() {}
? Not assigning anything is very convenient way to avoid answering controversial questions like this. – Mclymanprop2
. Identical behavior tovar x = y = function();
. function name ==y
. No ambiguity there, the function name is assigned when the function is created. In fact, becauseobj.prop1 = obj.prop2
doesn't work whilevar x = y
does is in itself confusing. – Mihevar x = y = function() ...
, the first name that I see isvar x
, so the fact that function is namedy
is arguably confusing and might be considered a bug. I think the proper way to assign a name when the function is created is to use unambiguous named function syntax:var x = y = function y() {}
– Mclymanx = y = function() { };
is evaluated asy = function() { }
(creating the function, which gives it its name, assigning toy
), then that resulting value (an existing function reference) is assigned tox
. Doing anything else would violate standard expression semantics and require extremely complicated mechanisms in the spec to achieve. – Vergaraa = b
assigns value ofb
toa
, normallyb
is not affected bya
in any way. Making special case whenb
is a function for deriving its name froma
seems arbitrary and unnecessary, given that there existed a way for a long time to give a name to any function. – Mclymanconst obj = {}; Object.defineProperty(obj, 'foo', {value:function(){}}); obj.foo.name;
returns'value'
... which is consistent but probably not intended. – Biggerstaffconst
(you get exactly the same results withlet
), and I'm not usingconst
for mutable variables -- you can't, on a compliant browser. I am usingconst
for constant variables referring to mutable objects, which is an entirely separate (and normal, in JS) thing. JavaScript doesn't currently have good support for deep-immutability (Object.freeze
and such still leave holes), and while immutability is fantastic and useful, it's not the only way to do things. – Vergarafoo.bar = function(){}
is not the same syntax asfoo={bar:function(){}}
the latter names functions the former does not. they have demonstrably different behaviors. In all cases the former will not change thename
property of the function. If it only changed it in the case of the property being equal to "", that would be a special case. That is what you're asking about. It would be an inconsistent behavior so why would a designer have to explicitly justify not doing it? – Indifferencefoo.bar = function(){}
does not name the function.foo = function(){}
does. That's the whole point of the question. There are something like a half-dozen syntaxes using formerly-anonymous expressions which are then assigned to something (a variable, object property during object initialization, default parameter value) which do, as of ES2015, assign names. There's one glaring omission. AWB referred to "objections" without elaboration. I want to know what they are (or were). – Vergara