Modules
لم يُترجم بعد؛ يُعرض باللغة الإنجليزية
A module is one JavaScript file with its own scope: nothing leaves it unless it is exported, and other modules get it only by importing it. Follow two real files, counter.js and main.js, as the engine loads them once, links each import to the exporting module's own binding, runs the dependency first, and then shows why an import is live, why a private name stays hidden, and why you cannot assign to an import.
5 أسئلة سريعة
اختر إجابة لتعرف السبب. تُحفَظ نتيجتك مع تقدّمك.
01counter.js has the line const step = 1; with no export. What can main.js do with step?
A module's top-level names stay inside the module. Only exported names can be imported, so typeof step in main.js gives "undefined".
02You run node main.js. Which line is printed first?
main.js imports from counter.js, so the engine loads and links both, then runs counter.js first. Its line 6 prints "counter.js runs" before main.js line 2 runs.
03main.js prints count, calls add(), and prints count again. What does it print?
An import is linked to the exporting module's own binding. When add() changes count inside counter.js, main.js sees the new value straight away.
04What happens on main.js line 6, count = 5; ?
Imports are read-only for the importer. Only counter.js can change count, for example through add(). Node.js and Chrome report "TypeError: Assignment to constant variable."
05Two different files both import from counter.js. How many times does counter.js run?
The engine keeps each module it has loaded and hands the same one to every importer, so its top-level code runs only once.
المسرد
- Module
- One JavaScript file with its own top-level scope. It shares names only through export.
- export
- A keyword that makes a name from this module available to other modules, as in export let count = 0.
- import
- A statement that links names exported by another module into this one, as in import { count, add } from "./counter.js".
- Binding
- A name joined to a value, such as count holding 0. let bindings can change; an import binding cannot be assigned by the importer.
- Live binding
- An import that always shows the exporting module's current value, because it is a link to that module's binding, not a copy.
- Entry point
- The module the program starts from, here main.js (node main.js or <script type="module" src="main.js">).
- Dependency
- A module that another module imports. Dependencies run before the modules that import them.
- TypeError
- The error JavaScript throws when a value is used in a way it does not allow, such as assigning to an import.
الملاحظات والمصادر
- To run the two files with Node.js, put them in one folder with a package.json that says "type": "module" (or name them .mjs) and run node main.js. In a browser, load main.js with <script type="module" src="main.js"> from a web server: module scripts opened from a file:// address are blocked.
- Imports are hoisted: the engine reads every import line and links it before the module's first line runs, wherever the import statements are in the file. Module code is always in strict mode.
- Before counter.js line 1 runs, count exists but is uninitialized (the temporal dead zone). Reading it then throws a ReferenceError. Function declarations such as add are set up while linking, so they work earlier.
- The error text depends on the engine. Chrome and Node.js print "TypeError: Assignment to constant variable."; Firefox and Safari word it differently. It is a TypeError in all of them.
- A module can also have one default export (export default ...), imported without braces: import counter from "./counter.js". import { count as total } renames an import, and import * as counter gathers them all.
- The boxes are a simplification: each module has a module environment record, and main.js's imports are indirect bindings that point at counter.js's own bindings (CreateImportBinding in ECMA-262).
اختبار يتاح بعد الخطوة الأخيرة.