Why does `obj.foo = function () {};` not assign the function `foo` to a function?

As in ES2015 (ES6), functions have their own names (including the official name property), and names are assigned when the function is created in different ways in addition to the obvious function declaration and the named function expression, such as assigning variables (the function name is given as a variable name ), the assignment of object properties (the function name is set as the property name), even the default values ​​for the function parameters (the function name is set to the parameter name). But assigning a property to an existing object (for example, not in the initializer of the object) does not assign a function property to this name. Why not? Of course, there must be a definite reason why this is undesirable / possible. What was it?

To be clear: I am not asking how to get around this. I ask what prevents this seemingly obvious case from being handled when there are so many others (including default parameter values!). There must be a good reason.

Please do not speculate or theorize. TC39 had a reason not to turn it on. I am wondering what the reason is. I went through the notes of the TC39 meeting , but have not yet found it. The closest I have found so far is Allen Wirfs-Brock answering Bergi's question to say that there was no consensus on how to do this for this form due to “various objections”, but unfortunately He did not say what these objections are.

More details:

All of the following assign functions to foo functions in a compatible 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 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 a property to an existing object outside the object initializer does not:

 const obj = {}; obj.foo = function() { }; console.log("Nope:", obj.foo.name); 

As far as I can tell, this is described by this section of the specification, which explicitly sets the function name if the IsIdentifierRef of LeftHandSideExpression is true (which, apparently, is not for property references).

So, repeating from above: Why not? Of course, there must be a definite reason why this is undesirable / possible. What was it?

+44
javascript function ecmascript-6
Dec 12 '16 at 18:51
source share
4 answers

Allen Wirfs-Brock responded in a discussion list with objections that prevented the TC39 consensus in the form obj.foo = function() { } :

... for

 cache[getUserSecret(user)] = function() {}; 

this will leak the user's secret information as a name value

and for

 obj[someSymbol] = function() {} 

this will leak the Symbol value as the name value

and for

  table[n]=function() {} 

name is likely to be a number string

There are counters of these objections (especially the last one, which is extremely weak, there are many other ways that the function automatically assigns a numeric string name), but this is not the point; The fact is that these were objections.

He also added that the operation IsPropertyReference, which will be required (where currently only IsIdentifierRef) ...

... is a run-time operation, and new semantics require a run-time definition. This is all unnecessary work-time work that can slow down the creation of function closures that appear inside loops.

So, in general, apparently, at the time the decision was made, these objections were transferred to this day (and, quite possibly, now too), therefore this form does not automatically name functions, while many others do.

+10
Jan 28 '17 at 16:28
source share

I read Allen Wirfs-Brock's answers, and he directly talks about possible security issues. I personally agree with him.

There may also be security issues. The name property potentially flows through the function object to the name of the variable to which it was originally assigned. But there is little that can do with the name of a local variable, outside the original function. But a missing property name is potentially more capable.

It seems that the objections he is talking about have something to do with it. If TC39 no longer explains this decision, it's hard to see why they left it like that :).

I'm sorry I can no longer help you.

-2
Dec 20 '16 at 10:22
source share

The idea of ​​a function called a little weirder. If you consider a function as another kind of variable, then its assignment should not change the internal state of the assigned variables. It looks like magic. This becomes more confusing if functions are passed (although it can be resolved by assigning names when creating a function, rather than passing it).

It seems to me that there is one group that hated the idea of ​​function names in general, and another group that loved them. They compromised the creation of object initializers only.

I personally agree with a group that thinks function names are strange, but I also think that once you do this, you have to go all the way. But people are so stupid. Compromises do not always make the most sense.

-2
Jan 9 '17 at 8:03
source share

I am not sure there is a definite reason.

 obj.foo = function (){}; 

first creates a link to express the function in obj, then binds foo to this link, which already has a (read-only) name.

So:

 obj.fooC = (new Function ()); console.log(obj.fooC.name);//'anonymous' obj.fooFE = function (){}; console.log(obj.fooFE.name);//'' obj.fooNFE = function a_name (){}; console.log(obj.fooNFE.name);//'a_name' 

- normal behavior.

Is there a write restriction:

 obj.foo = (function foo(){}); 
-2
Jan 12 '17 at 10:23
source share



All Articles