Chiamare una funzione "locale" all'interno di module.exports da un'altra funzione in module.exports?


327

Come si chiama una funzione all'interno di un'altra funzione in una module.exportsdichiarazione?

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

}

Sto provando ad accedere alla funzione foodall'interno della funzione bare sto ottenendo:

TypeError: Object # non ha un metodo 'pippo'

Se cambio this.foo()a solo foo()ottengo:

Errore di riferimento: foo non è definito


4
Ho testato il tuo codice e non ho errori. La funzione bar restituisce un indefinito perché non ha un'istruzione return. Sei sicuro di provare correttamente?
Ferchi,

1
Testato nella versione nodo v8.12.0e non genera più l'errore. barnon ha dichiarazioni di console.log(bla.bar())undefined
reso,

Risposte:


351

Cambia this.foo()inmodule.exports.foo()


1
@NamNguyen Calling exports.foo()sembra un po 'imbarazzante e difficile da leggere.
Afshin Mehrabani,

4
Penso che sia meglio della risposta accettata. Se si definiscono funzioni al di fuori dell'ambito delle esportazioni, si aggiunge un ulteriore livello di riferimento indiretto, e sebbene possa essere desiderabile a volte, rende più complicato, refactoring, ad esempio rinominare la funzione, trovare utilizzo della funzione, ecc.
Pierre Henry,

1
una risposta diretta alla domanda
Kermit_ice_tea

8
module.exports.foo()e exports.foo()non funziona per me con Node.js v5.8.0.
tra il

14
exports.foo () non funziona ma module.exports.foo () funziona con NodeJS v6.9.1
R. Canser Yanbakan il

191

Potresti dichiarare le tue funzioni al di fuori del module.exportsblocco.

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

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

Poi:

module.exports = {
  foo: foo,
  bar: bar
}

11
e se volessi accedere alle proprietà dell'oggetto dal metodo?
Rockstar5645,

1
Sto ottenendo TypeError: yourClass.youMethod non è una funzione quando l'ho fatto. Sto usando il nodo versione 6.9.1. Devi avere una dichiarazione di reso? Non ho dichiarazioni di ritorno poiché tutto il mio codice è asincrono nelle funzioni.
Brett Mathe,

1
Bel confronto di stili diversi - gist.github.com/kimmobrunfeldt/10848413
Tadas V.

Implementazione molto bella! +1
realnsleo

3
O, più concisamente, usando ES6,module.exports = { foo, bar, }
Let Me Tink About It

118

Puoi anche farlo per renderlo più conciso e leggibile. Questo è quello che ho visto fare in molti dei moduli open source ben scritti:

var self = module.exports = {

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

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

}

Questa versione di Node.js è specifica? Sto provando questo con v5.8.0 e sta registrando indefinito.
tra il

1
@doublejosh Hai ... hai letto la domanda? Si sta chiedendo come si chiama una funzione esportata da un'altra. Non ha nulla a che fare con le restrizioni di accesso.
Finanzi la causa di Monica

1
Sì, l'ho letto, per favore rileggi. Questa risposta fa esportare foo () con il modulo, che va contro il punto di una funzione "locale" chiamata solo all'interno del modulo.
doublejosh

66

È inoltre possibile salvare un riferimento all'ambito globale del modulo al di fuori della definizione (module.) Exports.somemodule:

var _this = this;

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

exports.someotherfunction = function() {
   _this.somefunction();
}

È una soluzione più pulita!
IvanZh,

non c'è bisogno di questo e puoi semplicemente usarlo dove ne hai bisogno
Yuki

usato thisdirettamente, non è necessario dichiarare_this
Dario

1
Quel suggerimento è utile una volta thisnon è più il diritto this. (Promesse e callback)
Andrew McOlash

Mi piace questa soluzione la migliore perché fornisce anche un esempio di scoping nei moduli NodeJS.
miguelmorin,

40

Un'altra opzione, e più vicina allo stile originale dell'OP, è quella di mettere l'oggetto che si desidera esportare in una variabile e fare riferimento a quella variabile per effettuare chiamate ad altri metodi nell'oggetto. Puoi quindi esportare quella variabile e sei a posto.

var self = {
  foo: function (req, res, next) {
    return ('foo');
  },
  bar: function (req, res, next) {
    return self.foo();
  }
};
module.exports = self;

25
const Service = {
  foo: (a, b) => a + b,
  bar: (a, b) => Service.foo(a, b) * b
}

module.exports = Service

3
Ciò è particolarmente utilizzabile perché il tuo codice è presente Service.foo()e anche il tuo codice client chiamerà Service.foo()con lo stesso nome.
Vince Bowdren,

Questa è una risposta perfetta!
Jayant Varshney,

16

A partire da Node.js versione 13 è possibile sfruttare i moduli ES6 .

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

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

Seguendo l'approccio di classe:

class MyClass {

    foo() {
        return 'foo';
    }

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

module.exports = new MyClass();

Ciò creerà un'istanza della classe una sola volta, a causa della memorizzazione nella cache del modulo del nodo:
https://nodejs.org/api/modules.html#modules_caching


e come si chiama un metodo statico con questo approccio?
Plixxer,

@CodeofGod Basta chiamarlo come si chiamerebbe qualsiasi altro metodo statico. In questo caso, se fooera statico si chiama da dentro barin questo modo: MyClass.foo().
m.spyratos,

sì, lo capisco, ma come lo chiameresti da un controller che lo sta importando come ... const oAccounts = require ("...");
Plixxer,

È possibile esportare la classe effettiva, non un'istanza della classe. In questo modo puoi usare i suoi metodi statici. Se poi devi usare i suoi metodi di istanza, dovrai istanziare la classe nel tuo controller.
m.spyratos,

6

Per risolvere il tuo problema, ho apportato alcune modifiche a bla.js e funziona,

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

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

e nessuna modifica in app.js

var bla = require('./bla.js');
console.log(bla.bar());

1
Nella barra delle funzioni, this.foo () non funziona ... deve essere foo ()
Falcoa,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.