Exporting classes with node.js
Asked Answered
S

4

38

I have the following test code that is being ran by jasmine-node in a file called bob_test.spec.js

require('./bob');

describe("Bob", function() {
  var bob = new Bob();

  it("stating something", function() {
    var result = bob.hey('Tom-ay-to, tom-aaaah-to.');
    expect(result).toEqual('Whatever');
  });
});

In order to make the test pass, I've written the following production code in a file called bob.js

"use strict";

var Bob = function() {
}

Bob.prototype.hey = function (text) {
  return "Whatever";
}

module.exports = Bob;

When I run the test - using jasmine-node . - I get the following F

Failures:

1) Bob encountered a declaration exception
Message:
    ReferenceError: Bob is not defined
Stacktrace:
    ReferenceError: Bob is not defined
    at null.<anonymous> (/Users/matt/Code/oss/deliberate-practice/exercism/javascript/bob/bob_test.spec.js:4:17)
    at Object.<anonymous> (/Users/matt/Code/oss/deliberate-practice/exercism/javascript/bob/bob_test.spec.js:3:1)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.require (module.js:364:17)
    at require (module.js:380:17)

Finished in 0.02 seconds
1 test, 1 assertion, 1 failure, 0 skipped

Based on what I understand about Javascript, I feel like this should work. What does node.js do differently with constructor functions and module exports that prevents this from working I like think it should?

Strafe answered 2/8, 2013 at 14:59 Comment(0)
O
60

require returns an object, you should store it somewhere

var Bob = require('./bob');

and then use this object

var bobInstance = new Bob();
Overcautious answered 2/8, 2013 at 15:3 Comment(0)
S
11

If you can use ECMAScript 2015 you can declare and export your classes and then 'import' your classes using destructuring with no need to use an object to get to the constructors.

In the module you export like this

class Person
{
    constructor()
    {
        this.type = "Person";
    }
}

class Animal{
    constructor()
    {
        this.type = "Animal";
    }
}

module.exports = {
    Person,
    Animal
};

then where you use them

const { Animal, Person } = require("classes");

const animal = new Animal();
const person = new Person();
Stilbite answered 2/3, 2018 at 20:26 Comment(0)
O
1

This should fix the error you were having while running your tests via jasmine-node:

// Generated by CoffeeScript 1.6.2
(function() {
  var Bob;

  Bob = (function() {
    function Bob() {}

    Bob.prototype.hey = function(what) {
      return 'Whatever.';
    };

    return Bob;

  })();

  module.exports = Bob;

}).call(this);
Onstage answered 2/8, 2013 at 23:5 Comment(0)
O
1

Improving marvin's answer:

"use strict";
var Bob = function() {}

Bob.prototype.hey = function (text) {
  return "Whatever";
}

module.exports = new Bob();

// another file
var Bob = require('./bob');
Bob.hey('text');

So you can create an object passing it to module.exports module.exports = new Bob();

Odericus answered 17/5, 2015 at 11:42 Comment(1)
This will create a singleton, though, which is not something you may want to, especially if the class has private variable that it writes to, because it will be shared across all instances where you use the Bob object. A better way is to export just Bob and then instantiate it in the module you intent to use it.Harrietteharrigan

© 2022 - 2024 — McMap. All rights reserved.