Eine "lokale" Funktion in module.exports von einer anderen Funktion in module.exports aufrufen?

326

Wie ruft man eine Funktion innerhalb einer anderen Funktion in einer module.exportsDeklaration auf?

app.js.
var bla = require('./bla.js');
console.log(bla.bar());
bla.js
module.exports = {

  foo: function (req, res, next) {
    return ('foo');
  },

  bar: function(req, res, next) {
    this.foo();
  }

}

Ich versuche, fooinnerhalb der Funktion auf die Funktion zuzugreifen bar, und erhalte Folgendes:

TypeError: Objekt # hat keine Methode 'foo'

Wenn ich this.foo()zu nur wechsle , foo()bekomme ich:

ReferenceError: foo ist nicht definiert

k00k
quelle
4
Ich habe Ihren Code getestet und habe keine Fehler. Die Balkenfunktion gibt undefiniert zurück, da sie keine return-Anweisung hat. Sind Sie sicher, dass Sie richtig testen?
Ferchi
1
In Knotenversion getestet v8.12.0und löst den Fehler nicht mehr aus. barhat keine return-Anweisung, so dass das Laufen console.log(bla.bar())einfach zurückkehrtundefined
VladNeacsu

Antworten:

350

Wechseln Sie this.foo()zumodule.exports.foo()

k00k
quelle
1
@NamNguyen Calling exports.foo()scheint etwas umständlich und schwer zu lesen.
Afshin Mehrabani
4
Ich denke, dass dies besser ist als die akzeptierte Antwort. Wenn Sie Funktionen außerhalb des Exportbereichs definieren, wird eine zusätzliche Indirektionsebene hinzugefügt, und obwohl dies manchmal wünschenswert sein kann, wird es komplizierter, die Funktion umzugestalten, z. B. umzubenennen, die Verwendung der Funktion zu finden usw.
Pierre Henry
1
eine direkte Antwort auf die Frage
Kermit_ice_tea
8
module.exports.foo()und exports.foo()arbeite nicht für mich mit Node.js v5.8.0.
Zwischen Gehirn
14
exports.foo () funktioniert nicht, aber module.exports.foo () funktioniert mit NodeJS v6.9.1
R. Canser Yanbakan
191

Sie können Ihre Funktionen außerhalb des module.exportsBlocks deklarieren .

var foo = function (req, res, next) {
  return ('foo');
}

var bar = function (req, res, next) {
  return foo();
}

Dann:

module.exports = {
  foo: foo,
  bar: bar
}
Brett
quelle
11
Was ist, wenn ich über die Methode auf Eigenschaften des Objekts zugreifen möchte?
Rockstar5645
1
Ich erhalte TypeError: yourClass.youMethod ist keine Funktion, als ich dies tat. Ich verwende die Knotenversion 6.9.1. Müssen Sie eine Rückgabeerklärung haben? Ich habe keine return-Anweisungen, da mein gesamter Code in den Funktionen asynchron ist.
Brett Mathe
1
Schöner Vergleich verschiedener Stile - gist.github.com/kimmobrunfeldt/10848413
Tadas V.
Sehr schöne Umsetzung! +1
Realnsleo
2
Oder genauer gesagt mit ES6module.exports = { foo, bar, }
Lassen Sie mich darüber nachdenken
118

Sie können dies auch tun, um es übersichtlicher und lesbarer zu machen. Dies habe ich in einigen der gut geschriebenen Open-Source-Module gesehen:

var self = module.exports = {

  foo: function (req, res, next) {
    return ('foo');
  },

  bar: function(req, res, next) {
    self.foo();
  }

}
Calvin Alvin
quelle
Ist diese Version von Node.j spezifisch? Ich versuche dies mit v5.8.0 und es wird undefiniert protokolliert.
Gehirn
1
@doublejosh Hast ... hast du die Frage gelesen? Es wird gefragt, wie Sie eine exportierte Funktion von einer anderen aufrufen. Es hat nichts mit Zugriffsbeschränkungen zu tun .
Fund Monica Klage
1
Ja, ich habe es gelesen, bitte noch einmal lesen. Diese Antwort führt dazu, dass foo () mit dem Modul exportiert wird, was gegen den Punkt einer "lokalen" Funktion verstößt, die nur innerhalb des Moduls aufgerufen wird.
DoubleJosh
66

Sie können einen Verweis auf den globalen Bereich des Moduls auch außerhalb der Definition (module.) Exports.somemodule speichern:

var _this = this;

exports.somefunction = function() {
   console.log('hello');
}

exports.someotherfunction = function() {
   _this.somefunction();
}
Ville
quelle
Es ist sauberer Lösung!
IvanZh
Sie brauchen das nicht und können es einfach dort verwenden, wo Sie es brauchen
Yuki
verwendet thisdirekt zu erklären nicht notwendig_this
Darius
1
Dieser Vorschlag ist nützlich, wenn er thisnicht mehr richtig ist this. (Versprechen und Rückrufe)
Andrew McOlash
Diese Lösung gefällt mir am besten, weil sie auch ein Beispiel für das Scoping in NodeJS-Modulen enthält.
Miguelmorin
40

Eine andere Option, die dem ursprünglichen Stil des OP näher kommt, besteht darin, das zu exportierende Objekt in eine Variable einzufügen und auf diese Variable zu verweisen, um andere Methoden im Objekt aufzurufen. Sie können diese Variable dann exportieren und loslegen.

var self = {
  foo: function (req, res, next) {
    return ('foo');
  },
  bar: function (req, res, next) {
    return self.foo();
  }
};
module.exports = self;
goozbox
quelle
25
const Service = {
  foo: (a, b) => a + b,
  bar: (a, b) => Service.foo(a, b) * b
}

module.exports = Service
david_adler
quelle
3
Dies ist besonders nützlich, da Ihr Code dort aufruft Service.foo()und Ihr Client-Code ebenfalls Service.foo()mit demselben Namen aufruft .
Vince Bowdren
Dies ist eine perfekte Antwort!
Jayant Varshney
16

Ab Node.js Version 13 können Sie ES6-Module nutzen .

export function foo() {
    return 'foo';
}

export function bar() {
    return foo();
}

Dem Klassenansatz folgen:

class MyClass {

    foo() {
        return 'foo';
    }

    bar() {
        return this.foo();
    }
}

module.exports = new MyClass();

Dadurch wird die Klasse aufgrund des Modul-Caching von Node nur einmal instanziiert:
https://nodejs.org/api/modules.html#modules_caching

m.spyratos
quelle
und wie ruft man mit diesem Ansatz eine statische Methode auf?
Plixxer
@CodeofGod Rufen Sie es einfach wie jede andere statische Methode auf. In diesem Fall foowürden Sie es, wenn es statisch wäre, von innen barwie folgt aufrufen : MyClass.foo().
m.spyratos
Ja, das verstehe ich, aber wie würden Sie es von einem Controller aufrufen, der es importiert wie ... const oAccounts = require ("...");
Plixxer
Sie können die tatsächliche Klasse exportieren, keine Instanz der Klasse. Auf diese Weise können Sie seine statischen Methoden verwenden. Wenn Sie dann jedoch die Instanzmethoden verwenden müssen, müssen Sie die Klasse in Ihrem Controller instanziieren.
m.spyratos
6

Um Ihr Problem zu beheben, habe ich einige Änderungen in bla.js vorgenommen und es funktioniert,

var foo= function (req, res, next) {
  console.log('inside foo');
  return ("foo");
}

var  bar= function(req, res, next) {
  this.foo();
}
module.exports = {bar,foo};

und keine Änderung in app.js.

var bla = require('./bla.js');
console.log(bla.bar());
Akash Jain
quelle
1
In der Funktionsleiste funktioniert this.foo () nicht ... es muss foo () sein
Falcoa