เรียกใช้ฟังก์ชัน“ local” ภายใน module.exports จากฟังก์ชั่นอื่นใน module.exports?


327

คุณเรียกฟังก์ชันจากภายในฟังก์ชันอื่นในการmodule.exportsประกาศได้อย่างไร

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

}

ฉันพยายามเข้าถึงฟังก์ชั่นfooจากภายในฟังก์ชั่นbarและฉันได้รับ:

TypeError: Object # ไม่มีเมธอด 'foo'

ถ้าฉันเปลี่ยนthis.foo()เป็นเพียงfoo()ฉันจะได้รับ:

ReferenceError: foo ไม่ได้ถูกกำหนดไว้


4
ฉันทดสอบโค้ดของคุณและไม่มีข้อผิดพลาด ฟังก์ชั่นบาร์กลับไม่ได้กำหนดเพราะไม่มีคำสั่งกลับมา คุณแน่ใจหรือว่ากำลังทดสอบอย่างถูกต้อง?
Ferchi

1
ทดสอบในรุ่นโหนดv8.12.0และไม่ทิ้งข้อผิดพลาดอีกต่อไป barไม่มีคำสั่งคืนสินค้าดังนั้นให้เรียกใช้console.log(bla.bar())เพียงแค่ส่งคืนundefined
VladNeacsu

คำตอบ:


351

เปลี่ยนthis.foo()เป็นmodule.exports.foo()


1
@NamNguyen การโทรexports.foo()ดูค่อนข้างอึดอัดและอ่านยาก
Afshin Mehrabani

4
ฉันคิดว่านี่ดีกว่าคำตอบที่ยอมรับ หากคุณกำหนดฟังก์ชั่นนอกขอบเขตการส่งออกจะเพิ่มระดับพิเศษของการอ้อมและในขณะที่มันอาจเป็นที่ต้องการบางครั้งมันทำให้ซับซ้อนมากขึ้นเพื่อ refactor เช่นเปลี่ยนชื่อฟังก์ชั่นของการใช้งานฟังก์ชั่นการค้นหา ฯลฯ
Pierre Henry

1
คำตอบสำหรับคำถามโดยตรง
Kermit_ice_tea

8
module.exports.foo()และexports.foo()ไม่ทำงานกับฉันด้วย Node.js v5.8.0
ระหว่าง

14
exports.foo () ไม่ทำงาน แต่ module.exports.foo () ทำงานกับ NodeJS v6.9.1
R. Canser Yanbakan

191

คุณสามารถประกาศฟังก์ชั่นของคุณนอกmodule.exportsบล็อก

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

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

แล้ว:

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

11
ถ้าฉันต้องการเข้าถึงคุณสมบัติของวัตถุจากวิธีการ
Rockstar5645

1
ฉันได้รับ TypeError: yourClass.youMethod ไม่ใช่ฟังก์ชันเมื่อฉันทำสิ่งนี้ ฉันใช้โหนดเวอร์ชั่น 6.9.1 คุณต้องมีใบแจ้งการคืนสินค้าหรือไม่? ฉันไม่มีคำสั่ง return เนื่องจากรหัสทั้งหมดของฉันเป็น async ในฟังก์ชั่น
Brett Mathe

1
การเปรียบเทียบที่ดีของสไตล์ที่แตกต่าง - gist.github.com/kimmobrunfeldt/10848413
Tadas V.

การใช้งานที่ดีมาก! +1
realnsleo

2
หรือใช้ ES6 อย่างรัดกุมยิ่งขึ้นmodule.exports = { foo, bar, }
ให้ฉัน

118

คุณสามารถทำสิ่งนี้เพื่อให้กระชับและอ่านได้ง่ายขึ้น นี่คือสิ่งที่ฉันเคยเห็นในโมดูลที่เขียนขึ้นมาอย่างเปิดเผย:

var self = module.exports = {

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

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

}

รุ่นนี้เป็น Node.js เฉพาะหรือไม่ ฉันกำลังลองกับ v5.8.0 และกำลังบันทึกไม่ได้กำหนด
ระหว่าง

1
@doublejosh ... คุณอ่านคำถามนี้แล้วหรือยัง? มันถามว่าคุณจะเรียกใช้ฟังก์ชันที่ถูกเอ็กซ์พอร์ตได้อย่างไร มันมีอะไรจะทำอย่างไรกับข้อ จำกัด การเข้าถึง
คดีของกองทุนโมนิกา

1
ใช่ฉันอ่านแล้วกรุณาอ่านใหม่ คำตอบนี้ทำให้การส่งออก foo () กับโมดูลซึ่งตรงข้ามกับจุดของฟังก์ชั่น "ท้องถิ่น" เรียกว่าเฉพาะภายในโมดูล
doublejosh

66

คุณยังสามารถบันทึกการอ้างอิงไปยังขอบเขตโกลบอลของโมดูลภายนอกคำจำกัดความของโมดูล

var _this = this;

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

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

มันเป็นทางออกที่สะอาดกว่า!
IvanZh

ไม่จำเป็นต้องใช้ _this นี้และคุณสามารถใช้สิ่งนี้ในที่ที่คุณต้องการ
Yuki

ใช้thisโดยตรงไม่จำเป็นต้องประกาศ_this
Darius

1
ข้อเสนอแนะที่เป็นประโยชน์ครั้งเดียวไม่ได้อยู่ทางด้านขวาthis this(สัญญาและการเรียกกลับ)
Andrew McOlash

ฉันชอบวิธีนี้ดีที่สุดเพราะมันยังให้ตัวอย่างของการกำหนดขอบเขตในโมดูล NodeJS
miguelmorin

40

ตัวเลือกอื่นและใกล้เคียงกับสไตล์ดั้งเดิมของ OP คือการวางวัตถุที่คุณต้องการส่งออกไปยังตัวแปรและอ้างอิงตัวแปรนั้นเพื่อทำการเรียกไปยังวิธีการอื่นในวัตถุ จากนั้นคุณสามารถส่งออกตัวแปรและคุณก็พร้อมที่จะไป

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
สิ่งนี้สามารถใช้งานได้โดยเฉพาะอย่างยิ่งเนื่องจากรหัสของคุณมีการโทรService.foo()และรหัสลูกค้าของคุณจะถูกเรียกService.foo()ด้วยชื่อเดียวกัน
Vince Bowdren

นี่คือคำตอบที่สมบูรณ์แบบ!
Jayant Varshney

16

เริ่มต้นด้วยNode.js เวอร์ชั่น 13คุณสามารถใช้ประโยชน์จากโมดูล ES6ได้

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

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

ทำตามวิธีการระดับ:

class MyClass {

    foo() {
        return 'foo';
    }

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

module.exports = new MyClass();

สิ่งนี้จะยกตัวอย่างคลาสได้เพียงครั้งเดียวเนื่องจากการแคชโมดูลของ Node:
https://nodejs.org/api/modules.html#modules_caching


และวิธีการหนึ่งเรียกวิธีการแบบคงที่ด้วยวิธีนี้ได้อย่างไร
Plixxer

@CodeofGod เพียงแค่เรียกมันว่าคุณจะเรียกวิธีการคงที่อื่น ๆ ในกรณีนี้ถ้าfooเป็นแบบคงที่คุณจะเรียกมันว่าจากภายในเช่นนี้bar MyClass.foo()
m.spyratos

ใช่ฉันเข้าใจแล้ว แต่คุณจะเรียกมันจากตัวควบคุมที่กำลังนำเข้ามันเหมือน ... const oAccounts = require ("... ");
Plixxer

คุณสามารถส่งออกคลาสจริงไม่ใช่อินสแตนซ์ของคลาส ด้วยวิธีนี้คุณสามารถใช้วิธีการคงที่ ถ้าคุณจำเป็นต้องใช้วิธีการอินสแตนซ์ของมันแล้วคุณจะต้องยกตัวอย่างคลาสในคอนโทรลเลอร์ของคุณ
m.spyratos

6

เพื่อแก้ไขปัญหาของคุณฉันได้ทำการเปลี่ยนแปลงเล็กน้อยใน bla.js และใช้งานได้

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

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

และไม่มีการดัดแปลงใน app.js

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

1
ในแถบฟังก์ชั่น this.foo () ไม่ทำงาน ... มันต้องเป็น foo ()
Falcoa
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.