ES6中的导入/导出如何工作?

时间:2016-08-12 07:45:56

标签: javascript node.js ecmascript-6

我正在学习ES6标准,所以我从一个非常基本的示例代码开始。

我的第一个档案是Rectangle.js

class Rectangle {
  perimeter(x, y) {
    return (2 * (x + y));
  }
  area(x, y) {
    return (x * y);
  }
}

export default class { Rectangle };

在另一个文件solve-1.js中,我有一些像这样的导入

import Rectangle from './Rectangle';

function solveRect(l, b) {
  if (l < 0 || b < 0) {
    console.log(`Rectangle dimensions should be greater than zero:  l = ${l} and b = ${b}`);
  } else {
    console.log(Rectangle.area(l, b));
  }
}

solveRect(2, 4);

我正在使用babel-node来运行此程序,我确实已经安装了预设,我的.babelrc包含

{
  "presets": [
    "es2015",
    "react",
    "stage-2"
  ],
  "plugins": []
}

报告的错误信息是

/Users/Kulbear/Desktop/NodeBear/Basic/solve-1.js:13
    console.log(_Rectangle2.default.area(l, b));
                                    ^

TypeError: _Rectangle2.default.area is not a function
    at solveRect (solve-1.js:7:27)
    at Object.<anonymous> (solve-1.js:12:1)
    at Module._compile (module.js:541:32)
    at loader (/usr/local/lib/node_modules/babel-cli/node_modules/babel-register/lib/node.js:148:5)
    at Object.require.extensions.(anonymous function) [as .js] (/usr/local/lib/node_modules/babel-cli/node_modules/babel-register/lib/node.js:158:7)
    at Module.load (module.js:458:32)
    at tryModuleLoad (module.js:417:12)
    at Function.Module._load (module.js:409:3)
    at Function.Module.runMain (module.js:575:10)
    at /usr/local/lib/node_modules/babel-cli/lib/_babel-node.js:160:24

编辑:

$ node --version
> v6.3.1

2 个答案:

答案 0 :(得分:17)

我看到两个问题:

  1. 这一行:

    export default class { Rectangle };
    

    ...正在尝试以某种方式创建一个包含Rectangle new 类。它将无法编译,但您已将第2阶段包含在.babelrc中,因此Babel认为这是尝试创建field。我想你可能想要:

    export default Rectangle;
    
  2. 您没有Rectangle.area(l, b)。您已将area定义为Rectangle 实例的方法,而不是静态方法。将其更改为静态:

    static area() {
        // ...
    }
    

    使用时,请使用实例

    var r = new Rectangle();
    r.area(/*...*/);
    

    从代码中,您需要static

  3. 所以把这两件事情放在一起(我也做了perimeter static):

    Rectangle.js

    class Rectangle {
      static perimeter(x, y) {
        return (2 * (x + y));
      }
      static area(x, y) {
        return (x * y);
      }
    }
    
    export default Rectangle;
    

    solve-1.js

    import Rectangle from './Rectangle';
    
    function solveRect(l, b) {
      if (l < 0 || b < 0) {
        console.log(`Rectangle dimensions should be greater than zero:  l = ${l} and b = ${b}`);
      } else {
        console.log(Rectangle.area(l, b));
      }
    }
    solveRect(2, 4);
    

    使用:

    $ babel-node solve-1.js 
    8
    

    几个旁注:

    1. 如果您愿意,可以组合导出和类声明:

        export default class Rectangle {
            // ...implementaton
        }
      

      请注意,这是一个声明,因此与其他导出不同,它不会以;handy reference结尾;尽管包含一个是无害的。)

    2. 如果Rectangle 只有static个方法,那么它就没有理由成为一个类;只使用静态函数的命名导出:

      export function perimeter {
          // ...
      }
      export function area {
          // ...
      }
      

      然后人们导入可以使用命名导入语法,如果他们只想要其中一个:

      import area from './Rectangle';
      

      ...如果他们想要所有这些,他们可以使用命名空间导入:

      import * as Rectangle from './Rectangle';
      

      然后使用Rectangle.area等。

      例如,它为模块的用户提供了灵活性。

答案 1 :(得分:5)

正如 T.J。已经说过,以下几行真的没有意义:

export default class { Rectangle };

它是有效的JS。您实际执行的操作是导出具有属性class的匿名"Rectangle",并且此属性的值是您之前定义的class Rectangle的构造函数。

因此,当您导入上述内容时,您必须执行以下操作才能使其正常工作:

import Rectangle from './Rectangle';

const rect1 = new Rectangle();
const rect2 = new rect1.Rectangle();
rect2.area(5,5);

当然这不是你想要做的。你真正想要的是:

export default Rectangle;

此外,您似乎只想要一些方法而不是构建整个类。至少在您的示例中,您没有创建Rectangle对象的实例。

如果是这种情况,我建议您删除课程,并执行以下操作:

export function perimeter (x, y) {
  return (2 * (x + y));
}
export function area(x, y) {
  return (x * y);
}

然后,您可以执行以下操作以导入和使用已定义的方法:

import * as Rectangle from './Rectangle';
console.log(Rectangle.area(5,5));