¿Llamar a una función "local" dentro de module.exports desde otra función en module.exports?


327

¿Cómo se llama a una función desde otra función en una module.exportsdeclaración?

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

}

Estoy tratando de acceder a la función foodesde dentro de la función bary obtengo:

TypeError: Object # no tiene el método 'foo'

Si cambio this.foo()a solo foo()obtengo:

ReferenceError: foo no está definido


44
Probé tu código y no tengo errores. La función de barra devuelve indefinido porque no tiene declaración de devolución. ¿Estás seguro de que estás probando correctamente?
Ferchi

1
Probado en la versión de nodo v8.12.0y ya no arroja el error. barno tiene declaración de devolución, por lo que la ejecución console.log(bla.bar())simplemente regresaundefined
VladNeacsu

Respuestas:


351

Cambiar this.foo()amodule.exports.foo()


1
@NamNguyen Calling exports.foo()parece un poco incómodo y difícil de leer.
Afshin Mehrabani

44
Creo que esto es mejor que la respuesta aceptada. Si define funciones fuera del alcance de las exportaciones, que añade un nivel adicional de direccionamiento indirecto, y si bien puede ser a veces deseables, lo hace más complicado, a perfeccionar por, por ejemplo, cambiar el nombre de la función, el uso del hallazgo de la función, etc
Pierre Henry

1
una respuesta directa a la pregunta
Kermit_ice_tea

8
module.exports.foo()y exports.foo()no funciona para mí con Node.js v5.8.0.
betweenbrain

14
exportaciones.foo () no funciona pero module.exports.foo () funciona con NodeJS v6.9.1
R. Canser Yanbakan

191

Puede declarar sus funciones fuera del module.exportsbloque.

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

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

Luego:

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

11
¿Qué pasa si quisiera acceder a las propiedades del objeto desde el método?
Rockstar5645

1
Recibo TypeError: yourClass.youMethod no es una función cuando hice esto. Estoy usando la versión de nodo 6.9.1. ¿Tiene que tener una declaración de devolución? No tengo declaraciones de devolución ya que todo mi código es asíncrono en las funciones.
Brett Mathe

1
Buena comparación de diferentes estilos - gist.github.com/kimmobrunfeldt/10848413
Tadas V.

Muy buena implementación! +1
realnsleo

3
O, de manera más concisa usando ES6,module.exports = { foo, bar, }
Déjenme pensarlo el

118

También puede hacer esto para hacerlo más conciso y legible. Esto es lo que he visto hacer en varios de los módulos de código abierto bien escritos:

var self = module.exports = {

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

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

}

¿Es específica esta versión de Node.js? Estoy intentando esto con v5.8.0 y está registrando indefinido.
betweenbrain

1
@doublejosh ¿... leíste la pregunta? Se pregunta cómo llamar a una función exportada desde otra. No tiene nada que ver con restricciones de acceso.
Fondo de la demanda de Mónica

1
Sí, lo leí, vuelve a leerlo. Esta respuesta hace que foo () se exporte con el módulo, lo que va en contra del punto de una función "local" que solo se llama dentro del módulo.
doublejosh

66

También puede guardar una referencia al alcance global del módulo fuera de la definición (module.) Exports.somemodule:

var _this = this;

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

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

¡Es una solución más limpia!
IvanZh

no necesita el _esto y simplemente puede usarlo donde lo necesite
Yuki

usado thisdirectamente, no es necesario declarar_this
Darius

1
Esa sugerencia es útil una vez thisque ya no es la correcta this. (Promesas y devoluciones de llamada)
Andrew McOlash

Esta solución me gusta más porque también da un ejemplo de alcance en los módulos NodeJS.
miguelmorin

40

Otra opción, y más cercana al estilo original del OP, es colocar el objeto que desea exportar en una variable y hacer referencia a esa variable para realizar llamadas a otros métodos en el objeto. Luego puede exportar esa variable y listo.

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
Esto es particularmente útil porque su código está llamando Service.foo(), y su código de cliente también llamará Service.foo()con el mismo nombre.
Vince Bowdren

Esta es una respuesta perfecta!
Jayant Varshney

16

A partir de la versión 13 de Node.js , puede aprovechar los módulos ES6 .

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

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

Siguiendo el enfoque de clase:

class MyClass {

    foo() {
        return 'foo';
    }

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

module.exports = new MyClass();

Esto creará una instancia de la clase solo una vez, debido al almacenamiento en caché del módulo de Node:
https://nodejs.org/api/modules.html#modules_caching


¿Y cómo se llama a un método estático con este enfoque?
Plixxer

@CodeofGod Simplemente llámelo como llamaría a cualquier otro método estático. En este caso, si fooera estática que le llama desde el interior de barla siguiente manera: MyClass.foo().
m.spyratos

sí, lo entiendo, pero ¿cómo lo llamarías desde un controlador que lo está importando como ... const oAccounts = require ("...");
Plixxer

Puede exportar la clase real, no una instancia de la clase. De esa manera puedes usar sus métodos estáticos. Sin embargo, si necesita utilizar sus métodos de instancia, deberá crear una instancia de la clase en su controlador.
m.spyratos

6

Para solucionar su problema, he realizado algunos cambios en bla.js y está funcionando,

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

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

y ninguna modificación en app.js

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

1
En la barra de funciones, this.foo () no funciona ... necesita ser foo ()
Falcoa
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.