篇の文章はあなたにES 6のモジュール化をわかるように手伝います.


先端モジュール化は先端工程化の礎石である.現在、大先端時代においてはモジュールの運用はさらに進んでいますが、将来を見据えて、es 6に提出されたimportとexportの形式は統一前後のモジュール化されているようです.
モジュール化の概要
ES 6のモジュール化を学ぶ前にまず復習します.前に出たモジュール化を比較的によく使うのは、CommunJS、AMD、CMDの3つの規定です.
それらの特徴と相互の違いは:
  • Common JSはサーバーに適用されます.書き方は
  • です.
    var clock = require('clock.js')
    clock.start();
    上記の例によれば、clockの呼び出しはclock.jsがロード成功を要求するのを待たなければならない.言い換えれば、同期動作である.これはまた、クライアントではなくサービス端末に広く適用されることになる.
  • AMD(Aynchronous Module Definition)は、非同期ローディングモジュールであり、ブラウザ(requireJsがこの仕様を適用した)に多く使われています.
    require([module],callback);
    
    // eg
    require(['clock.js'],function(clock){
      clock.start();
    })
    非同期的なロードを実現し、ブラウザの「仮死」問題を回避しているが、最初からすべての依存を書き出すのは論理的な順序に合わないという欠点もある.じゃ、CommunJSのように使う時にrequireを使って、非同期ロードをサポートして実行してもいいですか?
  • CMD(Common Module Definition)は近くに依存して、使う時またrequire(seajs推奨の規範)を使って、書き方は:
  • define(function(require,exports,module){
      var clock = require('clock.js');
      clock.start();
    })
    AMDとCMDの違いは、依存モジュールの実行タイミングが異なり、ローディング処理方式が異なるのではなく、両方とも非同期ローディングモジュールである.
    AMDは前置に依存しています.jsはモジュールに依存していますか?
    CMDは近くに依存しています.開発者は依存する時にrequireを使うことができます.しかし、jsプロセッサにとっては、コードを文字列解析にして初めて、どのモジュールに依存しているか、すなわち性能を犠牲にして開発の便利さを得ることができます.
    ES 6のモジュール設計思想はできるだけ静的になり、コンパイル時にモジュールの依存関係が確定できるようになります.
    Common JSとES 6モジュールを比較する:
    // CommonJS
    let { start, exists, readFile } = require('fs')
    //    
    // let _fs = require('fs')
    // let start = _fs.start, exists = _fs.exists, readFile = _fs.readFile
    
    // ES6
    import { start, exists, readFile } from 'fs'
    上記の例では、Common JSは実質的に全体ローディングfsモジュールで_fsオブジェクトを生成した後、オブジェクトからそれぞれ3つの方法を読み出して、「実行時ローディング」と呼ぶ.ES 6モジュールは3つの方法をロードします.「コンパイル時ローディング」といいます.
    ES 6モジュール化の文法規範
    厳格モード
    ES 6モジュールでは、自動的に厳格なモードを採用します.規定:
  • 変数は、先に
  • を宣言しなければなりません.
  • 関数パラメータは同じ名前の属性を持つことができません.
  • with
  • を使用できません.
  • 読み取り専用属性に対して値を割り当て、deleteは属性を削除してはいけない.直接エラーを報告する
  • .
  • は、変数delete propを削除することができません.属性delete global[prop]
  • だけ削除できます.
  • evalは、外層作用領域に変数を導入しない
  • .
  • evalおよびargumentsは、値
  • を再割り当てすることができません.
  • argumentsは自動反応関数パラメータの変化がありません.
  • 禁止thisは、グローバル
  • を指す.
  • 予約字を追加します.static、interface、protectedなどです.
  • 注意:ES 6モジュールで、トップレベルthisundefined、使われるべきではない.
    exportコマンド
    最初の種類:
    export var a = '123';
    export const _b = '2323'
    export let c = '2222' 
    第二種類:
    var a = '123';
    const _b = '2323'
    let c = '2222' 
    export {a, _b, c}; //   
    第三の種類(第二のキーワードにasキーワードを加えて名前を変えます)
    var a = '123';
    const _b = '2323'
    let c = '2222' 
    export {
        a as stream1,
      _b as stream2,
      c as stream3};
    注意:
  • export文が出力するインターフェースは、対応する値の参照、すなわち動的バインディング関係であり、このインターフェースを通じてモジュール内部のリアルタイムの値を取得することができる.Common JS仕様を比較します.CommunJSモジュールが出力するのは値のキャッシュです.ダイナミックアップデートは存在しません.
  • exportコマンドは、モジュールの最上階にあると規定していますが、ブロックレベルのスコープ内に出現すると、エラーが発生します.importは同じです.
  • importコマンド
    最初の種類:
    import {a, _b ,c} from './profile'
    第二種類:
    import {stream1 as firstVal} from './profile'
    importは静的な実行であり、式、変数、if構造は適用できません.
    if(x == 1){
      import { foo } from 'module1'
    }else{
      //...
    }
    import文はSingletonモードである.fooおよびbarは2つの文にロードされているが、対応するのは同じmy_moduleの例である.
    import { foo } from './module1'
    import { bar } from './module1'
    
    //    
    import {foo,bar} from './module1'
    モジュール全体のロード
    を使用してオブジェクトを指定できます.出力値はすべてこのオブジェクトにロードされます.
    import * as circle from './module1'
    circle.foo();
    circle.bar();
    モジュール全体のロード先のオブジェクトは静的に分析できますので、実行時の変更は許可されません.
    import * as circle from './module1'
    //           
    circle.foo = 123;
    circle.bar = function(){}
    標準出力
    export defaultコマンドはモジュールのデフォルト出力になります.
    // module2.js
    export default function(){
      console.log('123')
    }
    //    
    function a(){
      console.log('123')
    }
    export {a as default}; 
    importコマンドは、匿名関数に任意の名前を割り当てることができます.
    import defaultFn from './module2'
    //    
    import {default as defaultFn} from './module2'
    exportとimportの複合書き方
    export { foo, bar} from 'my_module';
    //    
    import {foo,bar} from 'my_module';
    export{foo,bar};
    export {es6 as default} from './someModule'
    //    
    import {es6} from './someModule'
    export default es6;
    import()方法
    前に述べたように、requireはダイナミックローディングであり、使う時にまたrequireを使うことができます.importは静的に実行され、コードの最上階にあるだけで、ブロックレベルの作用領域に存在してはいけない.これは、importがAMDの欠点のような運転中に実行できなくなります.そこで、import()関数を導入し、Nodeのrequire関数(CommunJS)に似ていますが、非同期的な負荷を実現する提案があります.
    定義:import()関数はimportと同じパラメータを受信し、Promiseオブジェクトに戻り、取得した値をthen法のコールバックパラメータとしてロードする.
    const main = document.querySelector('main')
    
    import(`./section-modules/${someVariable}.js`)
        .then(module => {
          module.loadPageInto(main);
        })
        .catch(err => {
        main.textContext = err.message;
      })
    //         :
    import('./module1.js')
    .then(({default:defaultFn,foo,bar}) => {
      console.log(defaultFn)
    })
    //             async   
    async function main() {
      const myModule = await import('./myModule.js');
      const {export1, export2} = await import('./myModule.js');
      const [module1, module2, module3] = 
            await Promise.all([
              import('./module1,js'),
              import('./module2.js'),
              import('./module3.js')
            ])
    }
    main();
    異なる仕様間のロード
    importロードCommon JSモジュール
  • importコマンドを使用してCommunJSモジュールをロードします.Nodeは自動的にmodule.export属性をモジュールのデフォルト出力とします.つまり、export default
    // a.js
    module.exports = {
      foo: 'hello',
      bar: 'world'
    }
    
    //  import      
    export default {
      foo: 'hello',
      bar: 'world'
    }
  • と同じです.
  • CommunJsモジュールは実行時に出力インターフェースが確定されますので、importコマンドでCommonJSモジュールをロードする場合は、全体入力(*)のみ使用できます.
    import {readfile} from 'fs' // 'fs' CommonJS     
    //     
    import * as express from 'express'
    const app = express.default();
  • requireロードES 6モジュール
  • requireコマンドがES 6モジュールをロードすると、すべての出力インターフェースが入力対象の属性となります.
    // es.js
    let foo = {bar : 'my-default'};
    exxport default foo;
    foo = null;
    
    // cjs.js
    const es_namespace = require('./es')
    console.log(es_namespace.default);// {bar:'my-default'}
  • Common JSを比較
    新しいファンがあっても、古い愛を忘れてはいけません.CommunJSとES 6のモジュール化との違いを引き続き比べて、ES 6のモジュール化の特性を理解してみましょう.
    出力の違い
    Common JSモジュールが出力するのは値のコピーで、ES 6が出力するのは値の参照です.
    // lib.js 
    let num = 3;
    function changeNum() {
      num = 4;
    }
    module.exports = {
      num: num,
      changeNum: changeNum,
    };
    
    //main.js
    var mod = require('./lib.js')
    console.log(mod.num); // 3
    mod.changeNum();
    console.log(mod.num); // 3
    これは、mod.numが元のタイプの値であるため、キャッシュされます.関数を作成することで、内部修正後の値を得ることができます.
    // lib.js 
    let num = 3;
    function changeNum() {
      num = 4;
    }
    module.exports = {
      get num(){
        return num
      },
      changeNum: changeNum,
    };
    
    //main.js
    var mod = require('./lib.js')
    console.log(mod.num); // 3
    mod.changeNum();
    console.log(mod.num); // 3
    比較ES 6モジュール:
    // lib.js 
    export let num = 3;
    export function changeNum() {
      num = 4;
    }
    
    //main.js
    import {num,changeNum} from './lib.js'
    console.log(num); // 3
    changeNum();
    console.log(num); // 4
    Common JSの循環ローディング
    ロード原理
    CommunJSモジュールはスクリプトファイルに対応しています.requireコマンドはモジュールをロードするたびにスクリプト全体を実行し、オブジェクトを生成します.このオブジェクトが生成されると、後で同じrequireコマンドを実行しても、直接にキャッシュに値を取ります.つまり、Common JSモジュールは何回ロードしても、最初のロード時に一回だけ実行され、その後再ロードする時に初めて実行された結果に戻ります.手動でシステムキャッシュをクリアしない限り、.
    ループローディング
    // a.js
    exports.done = false;
    var b = require('./b.js'); // 1. a.js    ,    b.js ; b.js     ,b:{done:true}
    console.log(' a.js ,b.done=%j',b.done); // 5. ' a.js ,b.done=true'
    exports.done = true;
    console.log('a.js    ') // 6. 'a.js    '
    
    // b.js
    exports.done = false;
    var a = require('./b.js') // 2. a:{done:false}
    console.log(' b.js ,a.done=%j',a.done); // 3. ' b.js ,a.done=false'
    exports.done = true;
    console.log('b.js    ') // 4. 'b.js    ',    a.js
    
    // main.js
    var a = require('./a.js');
    var b = require('./b.js');
    console.log(' main.js ,a.done=%j,b.done=%j',a.done,b.done); // 7.' main.js ,a.done=true,b.done=true'
    上のコードを見ることができます.第一に、b.jsでは、a.jsは実行されていません.第二に、main.jsが第二行まで実行された場合は、b.jsは再実行されません.キャッシュされたb.jsの実行結果を出力します.即ち、その第四行:exports.done = trueまとめてみます
  • Common JSモジュールがループローディングに遭遇したことにより、コードが全部実行された値ではなく、現在実行されている部分の値が返ってきます.
  • Common JSは、動的参照ではなく、出力値のキャッシュに入力される.
  • 比較:ES 6モジュールは動的参照であり、変数はキャッシュされません.
    // a.js
    import {bar} from './b.js';
    export function foo(){
      console.log('foo')
      bar();
      console.log('    ')
    }
    foo();
    
    // b.js
    import {foo} from './a.js' //    CommonJS,       undefined       
    export function bar(){
      console.log('bar')
      if(Math.random() > 0.5){
        foo();
      }
    }
    
    //        :foo bar     
    //         : foo bar foo bar