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


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


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
}

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

}

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

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;

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

module.exports = Service

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


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

1
Di bilah fungsi, this.foo () tidak berfungsi ... harus foo ()
Falcoa
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.