0

私はお互いに-依存共同二つのファイルがあります。デフォルトパラメータ未定義である

runner.js

import { build, altBuild } from './build'; 

const defaultValue = { 
    code: 42, 
}; 

export function options(value = defaultValue) { 
    return value; 
} 

export function altOptions(value = { code: 9 }) { 
    return value; 
} 

console.log(build()); 
console.log(altBuild()); 

build.js

import { options, altOptions } from './runner'; 

const buildParams = { 
    foo: 'bar', 
    extra: options(), 
} 

const altBuildParams = { 
    foo: 'bar', 
    extra: altOptions(), 
} 

export function build() { 
    console.log(options()); 
    return buildParams; 
} 

export function altBuild() { 
    console.log(altOptions()); 
    return altBuildParams; 
} 

私は希望ランニング出力は次のようになります。

{ code: 42 } 
{ foo: 'bar', extra: { code: 42 } } 
{ code: 9 } 
{ foo: 'bar', extra: { code: 9 } } 

しかし、その代わりに、それは次のようになります。

{ code: 42 } 
{ foo: 'bar', extra: undefined } 
{ code: 9 } 
{ foo: 'bar', extra: { code: 9 } } 

私はそれを回避することができますが、私はそれが起こっている理由について、本当に好奇心旺盛です。私はこの例を実行するためにNode 7.10とbabel-node 6.26を使用しています。


transpiledコードで更新:循環依存で

transpiled runner.js

Object.defineProperty(exports, "__esModule", { 
    value: true 
}); 
exports.options = options; 
exports.altOptions = altOptions; 

var _build = require('./build'); 

var defaultValue = { 
    code: 42 
}; 

function options() { 
    var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : defaultValue; 

    return value; 
} 

function altOptions() { 
    var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { code: 9 }; 

    return value; 
} 

console.log((0, _build.build)()); 
console.log((0, _build.altBuild)()); 

transpiled build.js

Object.defineProperty(exports, "__esModule", { 
    value: true 
}); 
exports.build = build; 
exports.altBuild = altBuild; 

var _runner = require('./runner'); 

var buildParams = { 
    foo: 'bar', 
    extra: (0, _runner.options)() 
}; 

var altBuildParams = { 
    foo: 'bar', 
    extra: (0, _runner.altOptions)() 
}; 

function build() { 
    console.log((0, _runner.options)()); 
    return buildParams; 
} 

function altBuild() { 
    console.log((0, _runner.altOptions)()); 
    return altBuildParams; 
} 
+0

翻訳されたコードを見ましたか? –

+0

私はFelixをやったけど、なぜ期待通りに動かないのか不思議に思った。質問を翻訳されたコードで更新します。 –

+0

2つのファイルの間にサイクリック依存関係がある理由は何ですか? –

答えて

1

宣言は直ちにある機能ながらそこに必要なすべてのもののために利用可能初期化命令である。これは、必要に応じて(怠惰な)起こるわけではありませんが、輸入の順番で定義され、完全なモジュール本体を評価します。どのファイルに応じて、あなたの場合は

は、あなたに、最初に必要とされるか

  1. だけで罰金が、その後初期化されていないbuildParamsを指しoptions()なるオブジェクト
  2. コールbuild()、とinialised defaultValueを取得し、結果をログに記録する
  3. build()を呼び出すと、altOptions()が正常に表示されますが、未初期化のaltBuildParamsを参照し、結果をログに記録します。
  4. defaultValue
  5. altOptions()

又は

  1. が初期化されていないdefaultValue
  2. altBuildParamsがで初期化取得する意味options()で初期化buildParamsを得るとaltBuildParamsを初期化取得されますoptions()で初期化buildParamsを得ますaltOptions()
  3. options()を取得し、buildParamsを使用するオブジェクト
  4. コールbuild()、とinialised defaultValueを取得し、altOptions()を取得し、altBuildParamsを使用した結果
  5. コールbuild()を、ログに記録し、その結果に
を記録

どちらの場合でも、実際のES6では例外をスローするが、バベルの移管ではundefinedで終わる、初期化されていない変数を参照します。あなたはこの仕事をすることはできません。

一般に、循環依存性を持つモジュールでは関数宣言のみを使用し、モジュールの先頭スコープ(変数の初期化を含む)では何も呼び出さない。 1つの大きなファイルに入れた場合、コードが少なくとも機能することを確認してください。