Для ответа прокрутите вниз до раздела TLDR ниже, но продолжайте читать, чтобы понять, почему.
Part1 - разница между функцией и вызовом функции
Ваша первая ошибка заключается в том, что вы экспортируете функцию, а не объект:
module.exports = function(data) // <---- this is a function
{
var globs = {
glob1 : data.toLowerCase(),
glob2 : data.toUpperCase()
}
return globs;
}
и в app.js вы делаете это:
console.log(globs.glob1); <--- globs is a function, not an object
когда вы должны делать это:
console.log(globs().glob1);
Почему это?Хорошо, давайте на мгновение забудем ваш модуль.Рассмотрим следующий код:
var a = function(){ return 2 };
console.log(a); // do you expect this to print a function or 2?
console.log(a()); // what do you expect this to print?
Это очень простое правило для функций во всех языках программирования, а не только в javascript: чтобы получить возвращаемое значение, необходимо вызвать функцию.Итак, в вашем коде:
function myExportedFunction (data) {
// some logic here...
return globs;
}
console.log(myExportedFunction); // prints a function
console.log(myExportedFunction()); // prints the globs object
console.log(myExportedFunction().glob1); // prints value of glob1
Так что на самом деле все просто.Волшебный синтаксис не происходит.Вы просто забыли вернуть объект glob и вместо этого используете указатель на функцию.Очевидно, что функция не имеет свойства glob1
, поэтому ее можно определить неопределенно.
Part2 - локальные переменные функции
OK.Допустим, вы внесли изменения, которые я рекомендовал выше.Существует очевидная проблема с тем, как была написана функция.Что происходит, когда вы делаете это:
var glob = require('glob.js')();
console.log(glob.glob1); // <--- prints "undefined"
Итак, первая проблема - вы не проверяете, передаете ли вы данные или ничего.Поэтому каждый раз, когда вы вызываете функцию, вы перезаписываете сохраненное значение.
Есть еще одна проблема: вы всегда возвращаете новый объект каждый раз, когда вызываете функцию.Давайте посмотрим, как работают локальные переменные при возврате:
function a () {
var data = {}
return data;
}
var x = a();
var y = a();
x.testing = 1;
y.testing = 2;
console.log(x.testing); // prints 1
console.log(y.testing); // prints 2
Итак, каждый раз, когда вы вызываете функцию, которая создает локальную переменную, вы возвращаете другой объект.На самом деле это не переменная, а буквальный синтаксис объекта:
var a = {};
// is basically the same as
var a = new Object();
Если мы изменим приведенный выше пример на:
function a () {
return {};
}
, он все равно будет вести себя так же.
TLDR
Итак, как нам это исправить?Все просто, создайте объект вне функции и проверьте, передали ли мы data
для инициализации:
var globs = {
glob1 : "",
glob2 : ""
}
module.exports = function(data)
{
globs.glob1 = data.toLowerCase();
globs.glob2 = data.toUpperCase();
return globs;
}
Теперь все должно работать:
В app.js
var global = require('glob.js')(data);
В mod.js
var global = require('glob.js')();
Эполог - модули - одиночные
Это может быть или не быть очевидным дляВы, почему выше должно работать.В случае, если вы уже знаете, почему я пишу это как ссылку для будущих читателей.
В файле node.js реализованы как правильные синглтоны.Поэтому в узле, если вам нужен синглтон, все, что вам нужно сделать, это написать модуль, вам не нужно реализовывать какой-либо специальный код для него.
Что это означает, что все глобальные переменные модуля (переменные области видимости модуля)распределяются между всеми требованиями.Вот очень простой модуль для совместного использования одной переменной среди всех модулей:
shared.js
var x = "";
module.exports = {
set: function (val) {x=val},
get: function () {return x}
}
a.js
var shared = require('./shared');
shared.set("hello world");
b.js
var shared = require('./shared');
console.log(shared.get()); // prints "hello world"
Мы используем эту функцию для объявления общей переменной glob
в приведенном выше коде.