Open rauschma opened 6 years ago
It might be useful to mention the .mjs
extension, which is increasingly getting adopted by tooling as a signal that the file is a JavaScript module as opposed to a classic script.
The experimental modules implementation in Node.js only works for .mjs
. Recently, the Node.js Modules Working Group agreed on the “minimal kernel” for what will one day become the unflagged implementation, and it states that .mjs
will continue to be supported out-of-the-box. (There is a plan to allow other extensions as well at the cost of additional configuration.)
@mathiasbynens The plan is to do both at the same time: Switch to .mjs
(once it is supported without a flag by Node.js) and explain the rationale behind .mjs
. With “Impatient JS”, I stick to established things.
@da-moo Thanks! A fix will be in the next release.
First, thanks for compiling a useful set of explanations!
export default foo();
Did you mean the ()
in that?
When I try it, I seem to be exporting the result of calling the function (which makes sense because ()
invoked it), but this doesn't fit either ther apparent intent of the statement or the notion of exports being static.
ubuntu@pettle:~/tmp$ node --experimental-modules B.mjs
(node:7610) ExperimentalWarning: The ESM module loader is experimental.
called foo
first line of B
bar = string result
ubuntu@pettle:~/tmp$ cat A.mjs
function foo() {
console.log("called foo");
return "string result";
}
export default foo();
ubuntu@pettle:~/tmp$ cat B.mjs
console.log("first line of B");
import bar from './A.mjs';
console.log("bar = " + bar);
ubuntu@pettle:~/tmp$ node --experimental-modules B.mjs
(node:7634) ExperimentalWarning: The ESM module loader is experimental.
called foo
first line of B
bar = string result
ubuntu@pettle:~/tmp$ node -v
v8.11.4
Or would this describe the intent of the example?
export default foo(); // export the return value of calling foo()
@mcast Good point. Both do indeed make sense. I’ll try to make this clearer in the next release.
Thank you for this book. I'm enjoying reading it!
I have a question:
RE: section https://exploringjs.com/impatient-js/ch_modules.html#naming-modules
could you please explain why underscore-casing does not work for default import and why it is not a good choice for functions?
Thanks!
Axel, this article (or chapter) made by day.
I've been a Java programmer almost from the Java beginnings, who had to move to TS/node a year ago and work on a node project which have been developed for years. The different module and import/export paradigms from JS, TS, node, nest drove me crazy. And if you work through tutorials on each of these technics you get always only the module view from this technics perspective. In the project I'm working all these technics are mixed and I haven't got a true view on how the module system works even for one year. Consequently refactorings habe been a big pain because I usually needed most of the time with updating dependencies by trial & error because there was no true understanding.
Your article is the first source I found where everything is put together in a compact way starting with the history and how it evolved.
Now I understand my project a lot better. Thank you very much!
Thank you, for your work. I have question about default export.
// Default exports export default function f() {} // declaration with optional name
and
27.7.1 The two styles of default-exporting There are two styles of doing default exports.
First, we can label existing declarations with export default:
export default function myFunc() {} // no semicolon! export default class MyClass {} // no semicolon!
I tried to figure out what existing declarations really mean, maybe it's about hoisting thing. But then I realized that this is actually named function expression and named class expression.
After export default
have to be expression, not declaration (or existing expression).
ESM creators have even considered another more explicit syntax with '=': export default = function myFunc() {};
Under the hood implicitly we set value (expression) to default
variable.
const funcExpression = function myFunc() {}
export default myFuncExpression;
const classExpression = class MyClass {}
export default classExpression;
So, is it existing declarations or expressions?
I tried to figure out what existing declarations really mean, maybe it's about hoisting thing. But then I realized that this is actually named function expression and named class expression.
@vovochka-dev: I should probably remove the word “existing”. I agree that that word makes this sentence slightly confusing.
They really are declarations – check out the three grammar rules for export default
in the ECMAScript specification. Two of them are for declarations.
@ApolloTang:
could you please explain why underscore-casing does not work for default import and why it is not a good choice for functions?
The common practice for JavaScript is to use camel case for functions. I’m going back and forth on underscore case: Maybe it shouldn’t be used at all (except for constants).
I tried to figure out what existing declarations really mean, maybe it's about hoisting thing. But then I realized that this is actually named function expression and named class expression.
@vovochka-dev: I should probably remove the word “existing”. I agree that that word makes this sentence slightly confusing.
They really are declarations – check out the three grammar rules for
export default
in the ECMAScript specification. Two of them are for declarations.
Thank you, Indeed it's declaration:
export default function add(a, b) {return a + b;}
console.log(add(2,2)) //4
One more thing. When I understood it was "aha moment" about export default const
problem. Consider some changes:
// Not legal JavaScript! export default const foo = 1, bar = 2, baz = 3; +// Legal JavaScript +export const foo = 1, bar = 2, baz = 3;
And also Cheat sheet does not contain this syntax:
export function f() {} export const one = 1; export {foo, b as bar}; +export const foo = 1, bar = 2, baz = 3;
I'm having trouble understanding this part,?
On the plus side, AMD modules can be executed directly. In contrast, CommonJS modules must either be compiled before deployment or custom source code must be generated and evaluated dynamically (think eval()). That isn’t always permitted on the web.
I think the author is trying to say something like this
Since you have a script element you can load as many scripts as you want dynamically, but can't you do the same in common JS? check some conditions, then call require
?
So basically since the common.js modules are not supported by javascript by default, you need to compile this to javascript, but why would you do this? if the node supports the require
function let it use it. well ofcourse if you are putting the code you have written using require, you need some sort of polyfill for that,
I have no idea about this sentence - "Custom source code must be generated and evaluated dynamically (think eval())"
In section 22.1, underneath the code snippit reads:
However the code snippit doesn't have a variable named
myModule
, did you meanmyLibrary
?