commmonjsとES 6及びrequirejsモジュール循環参照

10315 ワード

Commonjsモジュール循環参照
commmonjsは同期モジュールのローディング方式ですので、ローディングが完了してから次の動作が実行されます.このスクリプトを初めてローディングしたら、メモリの中にオブジェクトが生成されます.
{
  id: '...',
  exports: { ... },
  loaded: true,
  ...
}
スクリプトを実行して、他のところからこのモジュールを引用すると、そのexportsから出た内容を引用することができます.モジュールが2回目の参照をするときは、ロードを繰り返すことなく、最後のキャッシュを実行します.
循環参照がある場合は、すでに出力された部分だけを実行し、他の未導き出されたものは管理しないでください.
例えばa.jsとb.jsの相互参照:a.jsの内容は:
exports.done = false;

var b = require('./b.js');

exports.hello = false;

console.log(` a b.done   :`+b.done);

exports.done = true;

b.jsの内容は:
exports.done = false;

var a = require('./a.js');

console.log(` b a.done   :`+a.done);
console.log(` b a.hello   :`+a.hello);

exports.done = true;
main.jsでaとbを引用する.
var a = require('./a.js');
var b = require('./b.js');
console.log(a.done,b.done,b.hello);

var a1 = require('./a.js');
var b1 = require('./b.js');
console.log(a1.done,b1.done,b.hello);
a.jsでは、最初の行は、そのdone値をfalseとして導出し、2行目はb.jsを参照し、b.jsに入ると、最初の行はfalseとして、2行目はa.jsを参照し、この時はa.jsに入り、a.jsは2行だけを実行し、1つの値であるdoneはfalseとして出力される.したがって、b.jsの2行目のaはdone値にのみ参照でき、hello値はundefinedである.だからb.js出力
 b a.done   :false
 b a.hello   :undefined
b.js実行が完了したら、そのdone値はtrueで、a.jsの3行目を続けて、4行目の出力:
 a b.donetrue
この時a中doneはtrueで、helloはfalseで、b.jsはa中doneの値しか引用できません.したがって、console.log(a.done,b.done,b.hello);のこの行の出力:true true undefined、aとbを再び参照すると、再度実行されない.だから:
var a1 = require('./a.js');
var b1 = require('./b.js');
console.log(a1.done,b1.done,b.hello);
出力のみ可能です.true true undefined.
a.jsを:
exports.done = false;

setTimeout(function () {
    exports.done = 'anotherDone';
},5000);

var b = require('./b.js');
exports.hello = false;
console.log(` a b.done   :`+b.done);
exports.done = true;

main.jsは:
var a = require('./a.js');
var b = require('./b.js');
console.log(a.done,b.done,b.hello);

var a1 = require('./a.js');
var b1 = require('./b.js');

setTimeout(function () {
    console.log(a1.done,b1.done,b.hello);
},6000);
出力:
 b a.done   :false
 b a.hello   :undefined
 a b.done   :true
true true undefined
anotherDone true undefined
最後の行の出力a 1.doneはanothers Duneです.exportはメモリの中にオブジェクトが形成されています.a 1に格納されているのは彼に対する引用です.だから、a.jsがdoneを変えたらa 1を通じて体現できます.
ES 6 importモジュール循環参照
ES 6でモジュールに対する参照は、comonjsのようにrequireで入力しなければならないモジュールではなく、一つのモジュールの参照を保存しているだけですので、循環参照であっても間違いはありません.
even.js
import { odd } from './odd'
export var counter = 0;
export function even(n) {
    counter++;
    return n === 0 || odd(n - 1);
}
export function even2() {
   console.log(1234);
}
odd.js
import { even,  even2 } from './even';
export function odd(n) {
    even2();
    return n != 0 && even(n - 1);
}
mail.js
require('babel-core/register');
var even = require('./even');
even.even(6);
console.log(even.counter);
実行メール.js出力:
1234
1234
1234
4
AMD-RequireJs
requirejsに循環参照がある場合、参照したモジュールを部分requireで小包してエラーが発生しないようにすることができます.
a.js
define(['require'],function (require) {
    console.log('this is in a ');
    var b = require(['b'],function () {
        console.log('in a b.name:'+b.name);
    });
    function af() {
        console.log('this is af')
    }
    return {
        name:'aname',
        af:af
    };
});
b.js
define(['require'],function (require) {
    console.log('this is in b ');
    var a = require(['a'],function () {
        console.log('in b a.name:'+a.name);
    });
    function bf() {
        console.log('this is bf')
    }
    return {
        name:'bname',
        bf:bf
    };
});
mail.js
require(['a'],function (a) {
   a.af();
});
出力:
this is in a 
this is af
this is in b 
in a b.name:localRequire
in b a.name:localRequire