Panggil fungsi "lokal" dalam module.exports dari fungsi lain di module.exports?

327

Bagaimana Anda memanggil suatu fungsi dari dalam fungsi lain dalam module.exportsdeklarasi?

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

}

Saya mencoba mengakses fungsi foodari dalam fungsi bar, dan saya mendapatkan:

TypeError: Objek # tidak memiliki metode 'foo'

Jika saya mengubah this.foo()ke hanya foo()saya dapatkan:

ReferenceError: foo tidak didefinisikan

k00k
sumber
4
Saya menguji kode Anda dan tidak memiliki kesalahan. Fungsi bilah mengembalikan tidak terdefinisi karena tidak memiliki pernyataan pengembalian. Anda yakin menguji dengan benar?
Ferchi
1
Diuji dalam versi simpul v8.12.0dan tidak lagi membuang kesalahan. bartidak memiliki pernyataan pengembalian sehingga console.log(bla.bar())hanya menjalankan kembaliundefined
VladNeacsu

Jawaban:

351

Ubah this.foo()kemodule.exports.foo()

k00k
sumber
1
@NamNguyen Memanggil exports.foo()sepertinya agak canggung dan sulit dibaca.
Afshin Mehrabani
4
Saya pikir ini lebih baik daripada jawaban yang diterima. Jika Anda mendefinisikan fungsi di luar lingkup ekspor, itu menambah tingkat tipuan ekstra, dan meskipun kadang-kadang diinginkan, itu membuatnya lebih rumit, untuk refactor, misalnya mengubah nama fungsi, menemukan penggunaan fungsi, dll.
Pierre Henry
1
jawaban langsung untuk pertanyaan
Kermit_ice_tea
8
module.exports.foo()dan exports.foo()tidak bekerja untuk saya dengan Node.js v5.8.0.
otak
14
exports.foo () tidak berfungsi tetapi module.exports.foo () bekerja dengan NodeJS v6.9.1
R. Canser Yanbakan
191

Anda dapat mendeklarasikan fungsi Anda di luar module.exportsblok.

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

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

Kemudian:

module.exports = {
  foo: foo,
  bar: bar
}
Brett
sumber
11
bagaimana jika saya ingin mengakses properti objek dari metode ini?
Rockstar5645
1
Saya mendapatkan TypeError: yourClass.youMethod tidak berfungsi saat saya melakukan ini. Saya menggunakan simpul versi 6.9.1. Apakah Anda harus memiliki pernyataan pengembalian? Saya tidak memiliki pernyataan pengembalian karena semua kode saya async dalam fungsinya.
Brett Mathe
1
Perbandingan yang bagus dari berbagai gaya - gist.github.com/kimmobrunfeldt/10848413
Tadas V.
Implementasi yang sangat bagus! +1
realnsleo
3
Atau, lebih ringkas menggunakan ES6,module.exports = { foo, bar, }
Let Me Tink About It
118

Anda juga dapat melakukan ini agar lebih ringkas dan mudah dibaca. Ini yang saya lihat dilakukan di beberapa modul open source yang ditulis dengan baik:

var self = module.exports = {

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

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

}
Calvin Alvin
sumber
Apakah versi Node.js ini spesifik? Saya mencoba ini dengan v5.8.0 dan itu masuk tidak terdefinisi.
otak
1
@doublejosh Apakah ... apakah Anda membaca pertanyaan? Itu menanyakan bagaimana Anda memanggil satu fungsi yang diekspor dari yang lain. Ini tidak ada hubungannya dengan pembatasan akses.
Dana Gugatan Monica
1
Ya saya membacanya, silakan baca kembali. Jawaban ini membuat foo () diekspor dengan modul, yang bertentangan dengan fungsi "lokal" yang hanya dipanggil dalam modul.
doublejosh
66

Anda juga dapat menyimpan referensi ke ruang lingkup global modul di luar (modul.) Definisi ekspor. Modul:

var _this = this;

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

exports.someotherfunction = function() {
   _this.somefunction();
}
Ville
sumber
Ini solusi yang lebih bersih!
IvanZh
tidak perlu untuk _ini dan Anda hanya dapat menggunakan ini di mana Anda membutuhkannya
Yuki
digunakan thissecara langsung, tidak perlu menyatakan_this
Darius
1
Saran itu bermanfaat sekali thistidak lagi tepat this. (Janji dan panggilan balik)
Andrew McOlash
Saya suka solusi ini yang terbaik karena juga memberikan contoh pelingkupan dalam modul NodeJS.
miguelmorin
40

Pilihan lain, dan lebih dekat ke gaya asli OP, adalah untuk meletakkan objek yang ingin Anda ekspor ke dalam variabel dan referensi variabel itu untuk membuat panggilan ke metode lain di objek. Anda kemudian dapat mengekspor variabel itu dan Anda siap melakukannya.

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

module.exports = Service
david_adler
sumber
3
Ini terutama dapat digunakan karena kode Anda ada panggilan Service.foo(), dan kode klien Anda juga akan memanggil Service.foo()dengan nama yang sama.
Vince Bowdren
Ini jawaban yang sempurna!
Jayant Varshney
16

Dimulai dengan Node.js versi 13 Anda dapat memanfaatkan Modul ES6 .

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

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

Mengikuti pendekatan Kelas:

class MyClass {

    foo() {
        return 'foo';
    }

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

module.exports = new MyClass();

Ini akan membuat instance kelas hanya sekali, karena caching modul Node:
https://nodejs.org/api/modules.html#modules_caching

m.spyratos
sumber
dan bagaimana seseorang memanggil metode statis dengan pendekatan ini?
Plixxer
@ CodeofGod Sebut saja seperti yang Anda sebut metode statis lainnya. Dalam hal ini, jika fooitu statis Anda akan menyebutnya dari dalam barseperti ini: MyClass.foo().
m.spyratos
ya saya mengerti, tapi bagaimana Anda akan memanggilnya dari pengontrol yang mengimpornya seperti ... const oAccounts = memerlukan ("...");
Plixxer
Anda dapat mengekspor kelas yang sebenarnya, bukan turunan dari kelas. Dengan begitu Anda bisa menggunakan metode statisnya. Jika Anda kemudian perlu menggunakan metode instance-nya, maka Anda harus membuat instance kelas di controller Anda.
m.spyratos
6

Untuk memperbaiki masalah Anda, saya telah membuat beberapa perubahan di bla.js dan berfungsi,

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

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

dan tidak ada modifikasi di app.js

var bla = require('./bla.js');
console.log(bla.bar());
Akash Jain
sumber
1
Di bilah fungsi, this.foo () tidak berfungsi ... harus foo ()
Falcoa