Home » Nodejs » How do import / export work in ES6?

How do import / export work in ES6?

Posted by: admin November 29, 2017 Leave a comment

Questions:

I am learning the ES6 standard so I start from a very basic example code.

My first file is Rectangle.js

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

export default class { Rectangle };

And in another file solve-1.js, I have some imports like this

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

I am using babel-node to run this program, I do have required presets installed, my .babelrc contains

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

The reported error info was

/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
Answers:

I see two issues:

  1. This line:

    export default class { Rectangle };
    

    …is trying to create a new class somehow containing Rectangle. It would fail to compile, but you’ve included Stage 2 in your .babelrc and so Babel thinks it’s an attempt to create a field. I think you probably want:

    export default Rectangle;
    
  2. You have no Rectangle.area(l, b). You’ve defined area as a method of Rectangle instances, not as a static method. Either change it to a static:

    static area() {
        // ...
    }
    

    or when you use it, use an instance

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

    From the code, you want the static.

So taking those two things and putting them together (I made perimeter static as well):

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

Works:

$ babel-node solve-1.js 
8

A couple of side notes:

  1. If you like, you can combine the export and class declaration:

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

    Note that it’s a declaraion, so unlike other exports, it doesn’t end with ; (handy reference; although including one is harmless).

  2. If Rectangle only has static methods, there’s no reason for it to be a class at all; just use named exports of your static functions:

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

    Then people importing can use named import syntax if they just want one of those:

    import area from './Rectangle';
    

    …and if they want all of them, they can use a namespace import:

    import * as Rectangle from './Rectangle';
    

    and then use Rectangle.area or such.

    E.g., it gives the user of the module flexibility.

Questions:
Answers:

As T.J. already said, the following line does not really makes sense:

export default class { Rectangle };

But it is valid JS. What you’re actually doing is exporting an anonymous class that has as property "Rectangle" and the value of this property is the constructor for your previously defined class Rectangle.

So when you import the above you would have to do the following to have it work properly:

import Rectangle from './Rectangle';

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

Of course this is not really what you wanted to do. What you actually want is:

export default Rectangle;

Also, it seems like you just want some methods rather than construction a whole class. At least in your example you’re not creating an instance of the Rectangle object.

If this is the case I would suggest you remove the class and do something like this:

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

Then you can do the following to import and use the defined methods:

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