Как работает импорт/экспорт в ES6?

Я изучаю стандарт 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

Edit:

$ node --version
> v6.3.1

Ответ 1

Я вижу две проблемы:

  • Эта строка:

    export default class { Rectangle };
    

    ... пытается создать новый класс, содержащий Rectangle. Это не скомпилировалось, но вы включили Stage 2 в свой .babelrc, и поэтому Babel считает попыткой создать field, Я думаю, вы, вероятно, захотите:

    export default Rectangle;
    
  • У вас нет Rectangle.area(l, b). Вы определили area как метод экземпляров Rectangle, а не как статический метод. Либо измените его на статическую:

    static area() {
        // ...
    }
    

    или, когда вы используете его, используйте экземпляр

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

    Из кода вы хотите static.

Итак, возьмем эти две вещи и соединим их (я сделал 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

Несколько примечаний:

  • Если вам нравится, вы можете объединить декларацию экспорта и класса:

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

    Обратите внимание, что это декларация, так что в отличие от других экспонатов, она не заканчивается ; (полезной ссылкой, хотя включение одного из них безвредны).

  • Если Rectangle имеет только методы static, нет никаких оснований для того, чтобы он был классом вообще; просто используйте именованный экспорт ваших статических функций:

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

    Затем люди, импортирующие, могут использовать именованный синтаксис import, если они просто хотят одного из них:

    import area from './Rectangle';
    

    ... и если они хотят все из них, они могут использовать импорт пространства имен:

    import * as Rectangle from './Rectangle';
    

    а затем используйте Rectangle.area или такой.

    Например, он предоставляет пользователю гибкость модуля.

Ответ 2

Как 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));