第13章モジュールを使用したコードのカプセル化
他の言語は、パッケージなどの概念を使用してコードのスコープを定義します。ES6より前は、Javascriptは「すべてを共有する」メソッドを使用してコードをロードし、定義されたすべてはグローバルスコープを共有します。増加すると、このアプローチは名前の競合、セキュリティの問題などを引き起こします。
ES6の目標の1つは、スコープの問題を解決することであり、プログラムを整然と表示するために、モジュールが導入されています。
セクション1モジュールとは何ですか?
1.モジュールの定義
モジュールは自動的にstrictモードで実行され、実行中のJavaScriptコードを終了する方法はありません。
2.モジュールの機能
a)モジュールの最上位で作成された変数は、モジュールの最上位スコープにのみ存在し、グローバル共有スコープに自動的に追加されることはありません。
b)モジュールは、変数や関数など、外部からアクセス可能な要素をエクスポートする必要があります。
c)モジュールの上部では、この値は未定義です。
d)モジュールはHTMLスタイルのコードコメントをサポートしていません。
3.モジュールとスクリプトの違い
a)スクリプトは、モジュールではないJavaScriptコードです。
b)スクリプトとモジュールは、JavaScriptコードのロードと評価における重要な変更を表しています。
セクション2派生した基本的な文法
1.あなたが使用できるの輸出である他のモジュールに発表されたコードの一部が露出するキーワードを、プット輸出任意の変数、関数やクラス宣言の前には、モジュールからエクスポートします。
2. exportキーワードを除いて、すべての宣言はスクリプトとまったく同じです。デフォルトのキーワードを使用しない限り、この構文を使用して無名関数クラスをエクスポートすることはできません。
3.明示的にエクスポートされていない変数、関数、およびクラスはモジュール専用であり、モジュールの外部からアクセスすることはできません。
セクション3インポートの基本構文
1.モジュールからエクスポートされた関数は、importキーワードを使用して別のモジュールでアクセスできます。
2. importステートメントの2つの部分は、インポートするIDと、IDをインポートするモジュールです。例えば:
import { identifier1, identifier2 } from "./example.js";
3.インポート後の中括弧は、特定のモジュールからインポートされたバインディングを示します。
モジュールからバインディングをインポートすると、constを使用して定義されたかのようになります。その結果、同じ名前の別の変数を定義することも(同じ名前の別のバインディングをインポートすることを含む)、importステートメントの前に識別子を使用したりバインディングの値を変更したりすることもできません。
4.単一のバインディングまたは複数のバインディングをインポートできます。特別な状況では、モジュール全体を単一のオブジェクトとしてインポートし、すべてのエクスポートをオブジェクトの属性として使用できます。モジュール全体をインポートするこの形式は、名前空間インポートと呼ばれます。
5.エクスポートとインポートの重要な制限は、他のステートメントや関数の外部で使用する必要があることです。例えば:
if (flag)
{
export flag; //语法错误
}
//another example
function tryImport() {
import flag from "./example.js"; // 语法错误
}
セクション4エクスポートおよびインポート時の名前の変更
エクスポートおよびインポートの過程で、元の名前を使用したくない場合があります。現時点では、asキーワードを使用してこの要件を達成できます。例えば:
//导出的模块代码
function sum (sum1, sum2)
{
return num1 + num2;
}
export {sum as add}
//导入的模块代码
import { add } from "./example.js"
//也可以这样导入
import {add as sum } from "./example.js"
セクション5モジュールのデフォルト値
1.モジュールのデフォルト値は、defaultキーワードで指定された単一の変数、関数、またはクラスを参照します。モジュールごとに設定できるデフォルトのエクスポート値は1つだけです。エクスポート中にdefaultキーワードを複数回使用すると、構文エラーになります。デフォルト値をエクスポートする例を挙げてください。
export default function(num1, num2) {
return num1 + num2;
}
2. defaultはJavascriptのデフォルトのキーワードであるため、変数、関数、またはクラスの名前として使用することはできませんが、プロパティ名として使用することはできます。
3.デフォルト値と1つ以上のデフォルト以外のバインディングをエクスポートするモジュールの場合、1つのステートメントを使用してエクスポートされたすべてのバインディングをインポートできます。このとき、デフォルトのローカル名と、中括弧で囲まれたデフォルト以外の値をコンマで区切る必要があります。importステートメントでは、デフォルト値をデフォルト以外の値の前にソートする必要があることに注意してください。
詳細なコードについては、P.321-P.323を参照してください。
セクション6バインディングを再エクスポートする
1.シナリオによっては、インポートされた値を再エクスポートするために使用される場合があります。例えば:
import { sum } from "./example.js";
export { sum }
2.上記のコードは実行できますが、同じタスクを1つのステートメントで実行できます。
export { sum } from "./example.js"
この形式のエクスポートは、指定されたモジュールでsumステートメントを検索し、それをエクスポートします。
3.同じ値を異なる名前でエクスポートすることもできます。
export { sum as add } from "./example.js"
4。「*」を使用して、別のモジュールのすべての値をエクスポートできます。すべてをエクスポートすると、デフォルト値とすべての名前付きエクスポート値がエクスポートされ、モジュールからエクスポートされるコンテンツに影響する可能性があります。例:exmple.jsにデフォルトのエクスポート値がある場合、この構文を使用すると、新しいデフォルトのエクスポートを定義できません。
セクション7バインドせずにインポート
1.モジュール内の最上位の変数、関数、およびクラスはグローバルスコープに自動的に表示されませんが、これはモジュールがグローバルスコープにアクセスできないことを意味するものではありません。組み込みオブジェクト(配列やオブジェクトなど)の共有定義にモジュールでアクセスでき、これらのオブジェクトに加えられた変更は他のモジュールに反映されます。例えば:
//没有export或者import的代码
Array.prototype.pushAll() = function(items)
{
//items必须是一个数组
if (!Array.isArray(items))
{
throw new TypeError("参数必须是一个数组");
}
//使用内建的push()和展开运算符
return this.push(...items);
}
2.エクスポートまたはインポート操作がない場合でも、上記の例は有効なモジュールです。このコードは、モジュールまたはスクリプトとして使用できます。
3.この種のモジュールはエクスポートもインポートもされないため、より簡潔なインポート操作構文を使用してモジュールコードを実行でき、バインディングをインポートする必要はありません。例えば:
import "./example.js";
let colors = ["red", "green", "blue"];
let items = [];
items.pushAll(colors);
4.バインドされていないインポートは、ポリフィルとシムを作成するために使用される可能性が最も高いです。
セクション8ロードモジュール
ES6はモジュールの構文を定義しますが、これらのモジュールをロードする方法は定義しません。これは仕様の複雑さの表れであり、さまざまな実装環境(WebブラウザーやNode.js環境など)によって決定する必要があります。
1.Webブラウザでモジュールを使用します。
3つの方法があります:
1)<script>要素で、src属性を介してJavaScriptコードファイルをロードします。
2)JavaScriptコードは、src属性なしで<script>要素に埋め込まれています。
3)WebワーカーまたはServiceWorkerを介してJavaScriptコードファイルをロードします。
2. Webブラウザでのモジュールのロードシーケンス:
その中で、モジュールはHTMLファイルに表示される順序で実行されます。例えば:
<!-- 先执行这个标签 -->
<script type="module" src="module1.js"></script>
<!-- 再执行这个标签 -->
<script type="module" src="module2.js">
import {sum} from "./example.js"
let result = sum(1,2);
</script>
<!-- 最后执行这个标签 -->
<script type="module" src="module2.js"></script>
この例では、モジュールが最初に解析されてすべてのインポートステートメントが識別されます。次に、各インポートステートメントが取得プロセスをトリガーし、インポートされたすべてのリソースがロードおよび実行された後に現在のモジュールが実行されます。完全なロードシーケンスは次のとおりです。
1.module1.jsをダウンロードして解析します。
2.module1.jsにインポートされたリソースを再帰的にダウンロードして解析します。
3.インラインモジュールを解決します。
4.インラインモジュールにインポートされたリソースを再帰的にダウンロードして解析します。
5.module2.jsをダウンロードして解析します。
6.module2.jsにインポートされたリソースを再帰的にダウンロードして解析します。
ロード後、他の操作はドキュメントが完全に解析された後にのみ実行されます。ドキュメントが解析された後、次のアクションが発生します。
1.module1.jsにインポートされたリソースを再帰的に実行します。
2.module1.jsを実行します。
3.インポートされたリソースをインラインモジュールで再帰的に実行します。
4.インラインモジュールを実行します。
5.module2.jsにインポートされたリソースを再帰的に実行します。
6.module2.jsを実行します。
3.Webブラウザでの非同期モジュールのロード
<script>要素にasync属性があります。ドキュメント内の非同期スクリプトの順序は、スクリプトの実行順序に影響しません。スクリプトは、ダウンロードが完了した直後に、含まれているドキュメントが完了するのを待たずに実行されます。解析。
async属性は、スクリプトと同様の方法で実行されるモジュールでも使用できます。唯一の違いは、モジュールを実行する前に、モジュールにインポートされたすべてのリソースをダウンロードする必要があることです。
4.モジュールをワーカーとしてロードします
Webワーカーやサービスワーカーなどのワーカーは、Webページのコンテキスト外でJavaScriptコードを実行できます。ワーカーを作成する手順:インスタンスを作成し、JavaScriptファイルのアドレスを渡します。例えば:
//按照脚本的方式加载script.js
let worker = new Worker("script.js");
モジュールのロードをサポートするために、HTML標準の開発者は、これらのコンストラクターに2番目のパラメーターを追加しました。2番目のパラメータは、type属性のデフォルトが「script」であるオブジェクトです。typeをmoduleに設定して、モジュールファイルをロードできます。例えば:
//按照模块的方式加载module.js
let worker = new Worker("module.js", { type: "module" });
5.ブラウザモジュール指定子の解析
1)前の例のモジュール指定子(モジュール指定子)はすべて相対パスです(文字列 "./example.js"など)。ブラウザでは、モジュール指定子が次のいずれかの形式である必要があります。
・/で始まる分析はルートディレクトリから始まります。
・./で始まる分析は、現在のディレクトリから始まります。
・../で始まる分析は、親ディレクトリから始まります。
・URLフォーマット。
たとえば、https://www.example.com/modules/module.jsにモジュールファイルがあり、次のコードが含まれているとします。
// 从 https://www.example.com/modules/example.js 导入
import { first } from "./example.js";
// 从 https://www.example.com/example2.js 导入
import { second } from "../example.js";
// 从 https://www.example.com/example3.js 导入
import { third } from "/example.js";
// 从 https://www.example.com/example4.js 导入
import { fourth } from "https://www.example.com/example4.js";
2)モジュールを参照する場合、モジュール指定子は<script>タグとインポートの間でわずかに異なります。この違いは意図的なものです。例えば、
//无效的,没有以 /、 ./ 或 ../ 开头
import { first } from "example.js"
//无效的,没有以 /、 ./ 或 ../ 开头
import {second} from "example/index.js"
(このセクションの終わり)