【问题标题】:Default parameters from cross dependency is undefined交叉依赖的默认参数未定义
【发布时间】:2018-03-04 04:16:25
【问题描述】:

我有两个相互依赖的文件:

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());

构建.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 来运行这个示例。


用转译的代码更新:

转译的 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)());

编译后的 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;
}

【问题讨论】:

  • 你看转译的代码了吗?
  • 我做了 Felix,但它让我好奇,为什么它没有按预期工作。我会用转译的代码更新问题。
  • 这两个文件之间存在循环依赖的原因是什么?
  • 它基本上是代码Ghassen的组织。我当然可以用另一种方式组织它们来避免这种情况,但我很好奇为什么我不能让它像这样工作。

标签: javascript ecmascript-6 babeljs circular-dependency es6-modules


【解决方案1】:

在循环依赖中,虽然函数 声明 可立即用于其他一切,但需要有一个初始化顺序。这不会根据需要(惰性)发生,而是由导入的顺序定义,然后评估完整的模块主体。

在你的情况下,根据首先需要哪个文件,你要么

  1. 用对象初始化defaultValue
  2. 调用build(),得到options()就好了,然后引用未初始化的buildParams,并记录结果
  3. 调用build(),得到altOptions()就好了,但随后引用未初始化的altBuildParams,并记录结果
  4. get buildParams 初始化为options() 得到defaultValue
  5. 获取altBuildParams 初始化为altOptions()

  1. get buildParamsoptions() 初始化,它指的是未初始化的defaultValue
  2. 获取altBuildParams 初始化为altOptions()
  3. 用对象初始化defaultValue
  4. 调用build(),获取options()并使用buildParams,并记录结果
  5. 调用build(),得到altOptions()并使用altBuildParams,并记录结果

在任何一种情况下,您都引用了一个未初始化的变量,这会在真正的 ES6 中引发异常,但在 babel 转译中只会以 undefined 结束。您无法完成这项工作。

一般来说,只在具有循环依赖的模块中使用函数声明,并且不要在模块顶部范围内调用任何东西(包括变量初始化)。确保将代码放在一个大文件中至少可以工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-11-29
    • 2019-07-11
    • 1970-01-01
    • 2013-07-18
    • 1970-01-01
    • 2019-07-26
    • 2013-11-18
    • 1970-01-01
    相关资源
    最近更新 更多