-
Notifications
You must be signed in to change notification settings - Fork 26.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
7.1 says function expressions are always unnamed, but this changed in ES6 #794
Comments
Function name inference is implemented in hardly any of the browsers we support. In addition, relying on function name inference hinders greppability, so even in a pure ES6 environment, we wouldn't recommend that. (other subtler differences are that a function with an inferred name still doesn't have a lexical name binding in the function body, but that's not relevant here) |
Do you want to clarify that in the document itself? Via footnote, etc. |
Sure, that's a great idea for a footnote! |
... frome Style Guide: // bad
const foo = function () {
// ...
};
// good
const foo = function bar() {
// ...
}; So, you say, there should be 2 different names for one function? For example, // Is it worse
const sum = function(a, b) {
return a + b;
};
// than this?
const my_sum = function sum(a, b) {
return a + b;
}; I'm a begginer in JS/ES, can you tell, please, what are advantages of second method? |
@tandav In your last example, the first function doesn't have a |
@ljharb I tested it using babel and const foo = () => {} will be converted to var foo = function foo () {} So it does have an |
Yes, that's function name inference. Which can't always be relied on, and isn't supported in older engines. It remains preferred to use only explicit names, and never rely on inference. |
@ljharb -- Closely related to @tandav's question... Style guide example:
Is this specifically saying that not only should the function be named rather than an anonymous, but that name (here, Or would this also be adequate:
The example seems to imply that they should be distinct. If so, what is the advantage of that? |
@amberleyromo indeed, they should be distinct. This is to improve readability and greppability - it lets you use a short variable name, but a long, verbose, unique function name; also, when self-referencing the function, it makes it very clear that you're referring to the lexical name binding, not the containing variable. |
10.6 has an example that says
Is this in conflict with 7.1? |
@chengyin I don't see why; that function is named, and |
My understanding is the function is still declared in the scope, and hoisted. Example: foo();
export default function foo() {
console.log('bar');
} This will output Doesn't this cause the same issue as in "Why? Function declarations are hoisted, which means that it’s easy - too easy - to reference the function before it is defined in the file. This harms readability and maintainability"? I see this example similar to the first bad example in 7.1. |
My understanding of the spec is |
fair point - however, we have The alternative would be |
I have a readability suggestion: why not do this edit based off of the comment above (#794 (comment)):
|
I support VermillionAzure's suggestion, I came here to figure out why there was different names and that explains why concisely. |
I think that using a short name as a variable binding, one which will be used elsewhere to call the function, will harm readability in places where the function is called. One purpose of having a descriptive function name is to be more clear about what's happening in a section of code that calls the function. To find a function declaration, just grep To satisfy the block-scoping requirement as well as providing a name to the function, I think it would be perfectly acceptable to name the binding and the function the same thing, as @amberleyromo suggested (grep const initializeDatabase = function initializeDatabase() { }
// note: the name 'initializeDatabase' does *not* get hoisted It looks a little silly, but so does const foo = function bar() { } Also, as a note for the future: when function name inference becomes more commonplace, I believe the naming requirement should be removed altogether, as this whole thing is really a confusing, wonky-looking workaround. |
@ljharb When would this actually be a problem? I don't understand. Would it matter since the containing variable points to the function? |
If it’s reassigned, sure - which is something the engine has to keep track of, and could impact optimizations. |
@patgrasso made a good point I think. Can you maybe add the following?
|
See #794 (comment) |
It's hard enough to find a good name for a function, but we have to do it once more with a more verbose version? It may be good technically, but is it actually practical? |
I am interested in knowing then, how will this function be called? is it |
@rotimi-best due to rules of JS scoping, from outside the function, only |
This doesn't pass the common sense test. I understand that this is perhaps a good idea given that in the current point in time, you can't always assume that name inference will work. But is this really a sane way to address the issue going forward? |
@Borthralla yes, it is a sensible way going forward since there's intuitive places that names should be inferred that they forever will not be inferred, unrelated to supported target environments. |
We are closing in on 2021 and with IE11 support dropped from many library, as well as in our project, is function name inference an issue anymore? Which browsers are those, to be more specific? |
Yes. Many sites and companies still support older browsers, older than IE 11, but also, it’s just a better and clearer practice to have explicit names in your code instead of relying on inference. |
@ljharb You are so incredibly patient 👍 |
@ljharb I really agree with all the argument that @Borthralla put in the table. Please remember:
Also I tested with Babel in my project (in the same way that mentioned @JPeer264) throwing Error, and the stack trace of the error are identical using arrow function vs named function statement. At this point it should be just:
babel just traspiler to:
|
if Babel does that, then it may not be transpiling correctly, because non-arrow functions and arrow functions have actual runtime differences. If you want a named function, use one. |
Rule 7.1 states that I should use "named function expressions" and check it with "eslint: func-style" but eslint can check only that I use "function expression" or "function declaration". It did not check that the function expression is "named". Am I wrong? So the "eslint: func-style" is not applied to this rule. And there are no tools to check the whole codebase on this rule?
Rule 5.1
Rule 5.3
Rule 6.3
And more. In the style guide itself, there are tons of function expressions and function declarations and only 3 examples contain "named function expressions". |
@zhesha Yes, a style guide must by necessity sometimes violate itself in order to show clear examples. |
Like some others here, I'm challenged by this rule, but appreciate the reasoning behind it. If I'm calling the function by its variable, then I want that variable to be expressive, for readability. const foo = function fooLex() How about that? Excerpt from MDN JS guide: const factorial = function fac(n) {
return n < 2 ? 1 : n * fac(n - 1);
};
console.log(factorial(3)); // 6 Interesting that the function's lexical name is the short name, while the variable is more descriptive. |
@bubbavox i agree with you that the internal name should be more descriptive than the outer variable, but pragmatism may prefer the other approach at times :-) |
7.1 contains this statement:
Anonymous function expressions assigned to a binding are also named, per ES6 semantics (1.e.iii). That is, the "bad" example
const foo = function () { };
is the same asconst foo = function foo() { };
, which is equivalent to the "good" examplefunction foo() { }
in that respect.Should the statement be qualified that it's only a distinction for ES5 and below ?
The text was updated successfully, but these errors were encountered: