it-roy-ru.com

Какова цель Node.js module.exports и как вы его используете?

Какова цель Node.js module.exports и как вы его используете?

Похоже, я не могу найти какую-либо информацию по этому поводу, но она кажется довольно важной частью Node.js, поскольку я часто вижу ее в исходном коде. 

Согласно документации Node.js :

module 

Ссылка на актуальную module. В частности module.exports совпадает с объектом экспорта. Увидеть src/node.js для получения дополнительной информации.

Но это не очень помогает.

Что именно делает module.exports, и каким будет простой пример?

1311
mrwooster

module.exports - это объект, который фактически возвращается в результате вызова require.

Переменная exports изначально настроена на тот же объект (то есть это сокращенное обозначение «псевдоним»), поэтому в коде модуля вы обычно пишете что-то вроде этого:

var myFunc1 = function() { ... };
var myFunc2 = function() { ... };
exports.myFunc1 = myFunc1;
exports.myFunc2 = myFunc2;

экспортировать (или «выставить») функции с внутренней областью действия myFunc1 и myFunc2.

И в коде вызова вы будете использовать:

var m = require('./mymodule');
m.myFunc1();

где последняя строка показывает, как результат require (обычно) представляет собой простой объект, свойства которого могут быть доступны.

NB: если вы перезаписали exports, он больше не будет ссылаться на module.exports. Поэтому, если вы хотите назначить новый объект (или ссылку на функцию) на exports, вам также следует назначить этот новый объект для module.exports


Стоит отметить, что имя, добавляемое к объекту exports, не обязательно должно совпадать с именем внутренней области модуля для добавляемого значения, поэтому вы можете иметь:

var myVeryLongInternalName = function() { ... };
exports.shortName = myVeryLongInternalName;
// add other objects, functions, as required

с последующим:

var m = require('./mymodule');
m.shortName(); // invokes module.myVeryLongInternalName
1518
Alnitak

На это уже ответили, но я хотел бы добавить некоторые разъяснения ...

Вы можете использовать и exports, и module.exports, чтобы импортировать код в ваше приложение следующим образом:

var mycode = require('./path/to/mycode');

Основной вариант использования, который вы увидите (например, в примере кода ExpressJS), заключается в том, что вы устанавливаете свойства для объекта exports в файле .js, который затем импортируете с помощью require()

Таким образом, в простом примере подсчета вы могли бы иметь:

(counter.js):

var count = 1;

exports.increment = function() {
    count++;
};

exports.getCount = function() {
    return count;
};

... затем в вашем приложении (web.js или в любом другом файле .js):

var counting = require('./counter.js');

console.log(counting.getCount()); // 1
counting.increment();
console.log(counting.getCount()); // 2

Проще говоря, вы можете рассматривать требуемые файлы как функции, которые возвращают один объект, и вы можете добавлять свойства (строки, числа, массивы, функции, что угодно) к объекту, который возвращается, устанавливая их в exports.

Иногда вам нужно, чтобы объект, возвращаемый из вызова require(), был функцией, которую вы можете вызвать, а не просто объектом со свойствами. В этом случае вам также нужно установить module.exports, например так:

(sayhello.js):

module.exports = exports = function() {
    console.log("Hello World!");
};

(app.js):

var sayHello = require('./sayhello.js');
sayHello(); // "Hello World!"

Разница между export и module.exports объясняется лучше в этот ответ здесь .

206
Jed Watson

Обратите внимание, что механизм модулей NodeJS основан на CommonJS модулях, которые поддерживаются во многих других реализациях, таких как RequireJS, но также SproutCore, CouchDB, Wakanda, OrientDB, ArangoDB, RingoJS, TeaJS, SilkJS, curl.js или даже Adobe Photoshop (через PSLib ) . Вы можете найти полный список известных реализаций здесь .

Если ваш модуль не использует специфичные для узла функции или модуль, я настоятельно рекомендую вам затем использовать exports вместо module.exportsкоторый не является частью стандарта CommonJS, и в большинстве случаев не поддерживается другими реализациями.

Еще одна особенность NodeJS - это когда вы назначаете ссылку на новый объект для exports вместо простого добавления к нему свойств и методов, как в последнем примере, представленном Джедом Уотсоном в этом потоке. Я лично не одобряю эту практику, поскольку это нарушает поддержку циклических ссылок механизма модулей CommonJS. Это тогда не поддерживается всеми реализациями, и пример Jed должен быть написан таким образом (или подобным), чтобы обеспечить более универсальный модуль:

(sayhello.js):

exports.run = function() {
    console.log("Hello World!");
}

(app.js):

var sayHello = require('./sayhello');
sayHello.run(); // "Hello World!"

Или используя функции ES6

(sayhello.js):

Object.assign(exports, {
    // Put all your public API here
    sayhello() {
        console.log("Hello World!");
    }
});

(app.js):

const { sayHello } = require('./sayhello');
sayHello(); // "Hello World!"

PS: похоже, что Appcelerator также реализует модули CommonJS, но без поддержки циклических ссылок (см .: модули Appcelerator и CommonJS (кеширование и циклические ссылки) )

59
Alexandre Morgaut

Несколько вещей, о которых вы должны позаботиться, если назначите ссылку на новый объект для exports и/или modules.exports:

1. Все свойства/методы, ранее прикрепленные к исходному exports или module.exports, конечно, теряются, потому что экспортированный объект теперь будет ссылаться на другой новый

Это очевидно, но если вы добавляете экспортированный метод в начале существующего модуля, убедитесь, что собственный экспортируемый объект не ссылается на другой объект в конце

exports.method1 = function () {}; // exposed to the original exported object
exports.method2 = function () {}; // exposed to the original exported object

module.exports.method3 = function () {}; // exposed with method1 & method2

var otherAPI = {
    // some properties and/or methods
}

exports = otherAPI; // replace the original API (works also with module.exports)

2. Если один из exports или module.exports ссылается на новое значение, они больше не ссылаются на один и тот же объект

exports = function AConstructor() {}; // override the original exported object
exports.method2 = function () {}; // exposed to the new exported object

// method added to the original exports object which not exposed any more
module.exports.method3 = function () {}; 

3. Хитрое следствие. Если вы измените ссылку на exports и module.exports, трудно сказать, какой API выставлен (похоже, выигрывает module.exports)

// override the original exported object
module.exports = function AConstructor() {};

// try to override the original exported object
// but module.exports will be exposed instead
exports = function AnotherConstructor() {}; 
32
Alexandre Morgaut

свойство module.exports или объект экспорта позволяет модулю выбирать, что должно быть передано приложению

enter image description here

У меня есть видео на module_export доступно здесь

28
anish

При разделении кода вашей программы на несколько файлов module.exports используется для публикации переменных и функций для потребителя модуля. Вызов require() в вашем исходном файле заменяется соответствующим module.exports, загруженным из модуля.

Помните при написании модулей

  • Загрузка модулей кэшируется, только первоначальный вызов оценивает JavaScript.
  • Внутри модуля можно использовать локальные переменные и функции, не все нужно экспортировать.
  • Объект module.exports также доступен как сокращение exports. Но при возврате единственной функции всегда используйте module.exports.

module exports diagram

Согласно: «Модули Часть 2 - Написание модулей» .

17
pspi

ссылочная ссылка выглядит так:

exports = module.exports = function(){
    //....
}

свойства exports или module.exports, такие как функции или переменные, будут доступны за пределами 

есть что-то, на что вы должны обратить больше внимания: не экспортируйте override.

зачем ?

поскольку экспортирует только ссылку на module.exports, вы можете добавить свойства к экспорту, но если вы переопределите экспорт, ссылка будет прервана.

хороший пример :

exports.name = 'william';

exports.getName = function(){
   console.log(this.name);
}

плохой пример:

exports = 'william';

exports = function(){
     //...
}

Если вы просто хотите выставить только одну функцию или переменную, вот так:

// test.js
var name = 'william';

module.exports = function(){
    console.log(name);
}   

// index.js
var test = require('./test');
test();

этот модуль предоставляет только одну функцию, а свойство name является приватным для внешних пользователей.

8
qianjiahao

При загрузке и установке node.js существуют некоторые стандартные или существующие модули в файле node.js, напримерhttp, sysи т.д. 

Так как они уже находятся в файле node.js, когда мы хотим использовать эти модули, нам в основном нравятся import modules, но почему? потому что они уже присутствуют в node.js. Импортировать все равно, что брать их из node.js и помещать в свою программу. А потом с их помощью.

В то время какExportsявляется совершенно противоположным, вы создаете нужный модуль, скажем, модуль extension.js и помещаете этот модуль в node.js, вы делаете это путем его экспорта.

Прежде чем я что-то напишу здесь, запомните, module.exports.additionTwo такой же, как exports.additionTwo

Да, так вот почему нам нравится

exports.additionTwo = function(x)
{return x+2;};

Будь осторожен с пути

Допустим, вы создали модуль дополнения.js, 

exports.additionTwo = function(x){
return x + 2;
};

Когда вы запускаете это в командной строке NODE.JS:

node
var run = require('addition.js');

Это будет ошибка, сказав 

Ошибка: не удается найти модуль дополнения.js

Это связано с тем, что процесс node.js не может добавить дополнение.js, поскольку мы не упомянули путь. Итак, мы можем установить путь с помощью NODE_PATH

set NODE_PATH = path/to/your/additon.js

Теперь это должно успешно работать без каких-либо ошибок!

Еще одна вещь, вы также можете запустить файл дополнения.js, не устанавливая NODE_PATH, обратно к вашей командной строке nodejs:

node
var run = require('./addition.js');

Поскольку мы указываем здесь путь, говоря, что он находится в текущем каталоге ./, он также должен успешно работать. 

5
JumpMan

Модуль инкапсулирует связанный код в одну единицу кода. При создании модуля это можно интерпретировать как перемещение всех связанных функций в файл. 

Предположим, есть файл Hello.js, который включает две функции

sayHelloInEnglish = function() {
  return "Hello";
};
sayHelloInSpanish = function() {
  return "Hola";
};

Мы пишем функцию только тогда, когда утилита кода является более чем одним вызовом.

Предположим, что мы хотим увеличить полезность функции для другого файла, скажем, World.js, в этом случае экспортируется файл, который можно получить с помощью module.exports.

Вы можете просто экспортировать обе функции по приведенному ниже коду

var anyVariable={
 sayHelloInEnglish = function() {
      return "Hello";
    };
  sayHelloInSpanish = function() {
      return "Hola";
    }; 
}
module.export=anyVariable;

Теперь вам просто нужно указать имя файла в порядке World.js, чтобы использовать эти функции.

var world= require("./hello.js");
2
Shantanu Madane

Намерение:

Модульное программирование - это метод проектирования программного обеспечения, который подчеркивает разделение функциональности программы на независимую, сменные модули, такие, что каждый содержит все необходимое выполнить только один аспект желаемой функциональности.

Википедия

Я предполагаю, что становится трудно писать большие программы без модульного/многократно используемого кода. В nodejs мы можем создавать модульные программы, использующие module.exports, определяющие, что мы выставляем, и составлять нашу программу с require.

Попробуйте этот пример:

fileLog.js

function log(string) { require('fs').appendFileSync('log.txt',string); }

module.exports = log;

stdoutLog.js

function log(string) { console.log(string); }

module.exports = log;

program.js

const log = require('./stdoutLog.js')

log('hello world!');

выполнить

$ node program.js

привет, мир!

Теперь попробуйте заменить ./stdoutLog.js на ./fileLog.js.

1
Moriarty

Какова цель модульной системы?

Это выполняет следующие вещи:

  1. Сохраняет наши файлы от вздутие живота до действительно больших размеров. Наличие файлов, например, с 5000 строк кода, как правило, очень трудно решить во время разработки.
  2. Обеспечивает разделение интересов. Разделение нашего кода на несколько файлов позволяет нам иметь соответствующие имена файлов для каждого файла. Таким образом, мы можем легко определить, что делает каждый модуль и где его найти (при условии, что мы создали логическую структуру каталогов, которая по-прежнему остается вашей ответственностью).

Наличие модулей облегчает поиск определенных частей кода, что делает наш код более понятным.

Как это работает?

NodejS использует систему модулей CommomJS, которая работает следующим образом:

  1. Если файл хочет что-то экспортировать, он должен объявить это с использованием синтаксиса module.export
  2. Если файл хочет импортировать что-то, он должен объявить это с помощью синтаксиса require('file')

Пример:

test1.js

const test2 = require('./test2');    // returns the module.exports object of a file

test2.Func1(); // logs func1
test2.Func2(); // logs func2

test2.js

module.exports.Func1 = () => {console.log('func1')};

exports.Func2 = () => {console.log('func2')};

Другие полезные вещи, которые нужно знать:

  1. Модули кэшируются . Когда вы загружаете один и тот же модуль в 2 разных файла, модуль должен быть загружен только один раз. Второй раз require() вызывается на том же модуле, который извлекается из кэша.
  2. Модули загружаются синхронно . Такое поведение требуется, если оно было асинхронным, мы не могли бы сразу получить доступ к объекту, полученному из require().
0
Willem van der Veen