Kulbear Kulbear - 3 months ago 5
Javascript Question

How do import / export work in ES6?

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

Answer

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.

Comments