Викликати "локальну" функцію в 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: Об'єкт № не має методу 'foo'

Якщо я перейду this.foo()на просто, foo()я отримаю:

ReferenceError: foo не визначено


4
Я перевірив ваш код і не маю помилок. Функція бар повертається невизначеною, оскільки не має заяви про повернення. Ви впевнені, що ви тестуєте правильно?
Ферчі

1
Тестується у версії вузла v8.12.0і більше не видає помилку. barне має заяви про повернення, тому запущений console.log(bla.bar())просто повертаєтьсяundefined
VladNeacsu

Відповіді:


351

Змінити this.foo()наmodule.exports.foo()


1
@NamNguyen Calling exports.foo()здається трохи незручним і важким для читання.
Афшин Мехрабані

4
Я думаю, що це краще, ніж прийнята відповідь. Якщо визначити функції поза сферою експорту, додає додатковий рівень непрямого, і в той час як це може бути бажаними іноді, це робить його більш складним, щоб реорганізувати, наприклад , перейменування функції, використання знаходять функції і т.д.
П’єр Генрі

1
пряма відповідь на питання
Kermit_ice_tea

8
module.exports.foo()і exports.foo()не працюйте для мене з Node.js v5.8.0.
між

14
export.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. Чи потрібно мати декларацію про повернення? У мене немає заяв на повернення, оскільки весь мій код - це асинхронізація у функціях.
Бретт Матх

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

Ви також можете зберегти посилання на глобальний діапазон модуля поза визначенням (module.) Export.somemodule:

var _this = this;

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

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

Це більш чисте рішення!
ІванЖ

немає необхідності в цьому і ви можете просто використовувати це там, де вам потрібно
Юкі

використовується thisбезпосередньо, не потрібно декларувати_this
Дарій

1
Ця пропозиція корисна один раз this- це вже не право this. (Обіцянки та зворотні дзвінки)
Ендрю МакОлаш

Мені подобається це рішення найкраще, тому що воно також дає приклад визначення обсягу в модулях NodeJS.
miguelmorin

40

Інший варіант, ближчий до початкового стилю ОП, - поставити об'єкт, який ви хочете експортувати, в змінну і посилатись на цю змінну для здійснення викликів до інших методів в об'єкті. Потім можна експортувати цю змінну, і ви готові перейти.

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()з однаковим іменем.
Вінс Боудрен

Це ідеальна відповідь!
Джаянт Варшні

16

Починаючи з версії 13 Node.js, ви можете скористатися модулями 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 = requ ("...");
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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.