Делить переменные между файлами в Node.js?

Вот 2 файла:

// main.js
require('./modules');
console.log(name); // prints "foobar"

// module.js
name = "foobar";

Когда у меня нет "вар", это работает. Но когда у меня есть:

// module.js
var name = "foobar";

имя будет не определено в main.js.

Я слышал, что глобальные переменные плохие, и вам лучше использовать "var" перед ссылками. Но так ли это, когда глобальные переменные хороши?

8 ответов

Глобальные переменные почти никогда не бывают полезными (может быть, исключение или два там...). В этом случае, похоже, вы действительно хотите экспортировать свою переменную "name". Например,

// module.js
var name = "foobar";
// export it
exports.name = name;

Тогда в main.js...

//main.js
// get a reference to your required module
var myModule = require('./module');

// name is a member of myModule due to the export above
var name = myModule.name;

Я не могу найти сценарий, где глобальный var это лучший вариант, конечно, у вас может быть один, но посмотрите на эти примеры, и вы можете найти лучший способ сделать то же самое:

Сценарий 1. Поместите материал в конфигурационные файлы.

Вам нужно некоторое значение, которое одинаково для всего приложения, но оно меняется в зависимости от среды (производство, разработка или тестирование), типа почтовой программы, например, вам нужно:

// File: config/environments/production.json
{
    "mailerType": "SMTP",
    "mailerConfig": {
      "service": "Gmail",
      ....
}

а также

// File: config/environments/test.json
{
    "mailerType": "Stub",
    "mailerConfig": {
      "error": false
    }
}

(сделать аналогичный конфиг для dev тоже)

Чтобы решить, какая конфигурация будет загружена, создайте основной файл конфигурации (он будет использоваться во всем приложении)

// File: config/config.js
var _ = require('underscore');

module.exports = _.extend(
    require(__dirname + '/../config/environments/' + process.env.NODE_ENV + '.json') || {});

И теперь вы можете получить такие данные:

// File: server.js
...
var config = require('./config/config');
...
mailer.setTransport(nodemailer.createTransport(config.mailerType, config.mailerConfig));

Сценарий 2. Использование файла констант

// File: constants.js
module.exports = {
  appName: 'My neat app',
  currentAPIVersion: 3
};

И используйте это так

// File: config/routes.js

var constants = require('../constants');

module.exports = function(app, passport, auth) {
  var apiroot = '/api/v' + constants.currentAPIVersion;
...
  app.post(apiroot + '/users', users.create);
...

Сценарий 3. Использование вспомогательной функции для получения / установки данных.

Не большой поклонник этого, но, по крайней мере, вы можете отследить использование "имени" (приводя пример ОП) и поставить валидации на место.

// File: helpers/nameHelper.js

var _name = 'I shall not be null'

exports.getName = function() {
  return _name;
};

exports.setName = function(name) {
  //validate the name...
  _name = name;
};

И использовать это

// File: controllers/users.js

var nameHelper = require('../helpers/nameHelper.js');

exports.create = function(req, res, next) {
  var user = new User();
  user.name = req.body.name || nameHelper.getName();
  ...

Может быть случай использования, когда нет другого решения, кроме глобального var, но обычно вы можете поделиться данными в своем приложении, используя один из этих сценариев, если вы начинаете использовать node.js (как я когда-то недавно) попытался организовать способ обработки данных там, потому что это может действительно запутаться быстрый.

Если нам нужно совместно использовать несколько переменных, используйте следующий формат

//module.js
   let name='foobar';
   let city='xyz';
   let company='companyName';

   module.exports={
    name,
    city,
    company
  }

использование

  // main.js
    require('./modules');
    console.log(name); // print 'foobar'

Обновить

Сохраните любую переменную, которую хотите использовать как один объект. Затем передайте его загруженному модулю, чтобы он мог обращаться к переменной через ссылку на объект.

// myModule.js
var shared = null;

function init(obj){
    shared = obj;
}

module.exports = {
    init:init
}

,

// main.js
var myModule = require('./myModule.js');
var shares = {value:123};
myModule.init(shares);

Старый ответ

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

//myModule.js
var mainFunction = null; //You can also put function reference in a Object or Array

function functionProxy(func){
    mainFunction = func; //Save the function reference
}

// --- Usage ---
// setTimeout(function(){
//   console.log(mainFunction('myString'));
//   console.log(mainFunction('myNumber'));
// }, 3000);

module.exports = {
    functionProxy:functionProxy
}

,

//main.js
var myModule = require('./myModule.js');
var myString = "heyy";
var myNumber = 12345;

function internalVariable(select){
    if(select=='myString') return myString;
    else if(select=='myNumber') return myNumber;
    else return null;
}

myModule.functionProxy(internalVariable);


// --- If you like to be able to set the variable too ---
// function internalVariable(select, set){
//    if(select=='myString'){
//        if(set!=undefined) myString = set;
//        else return myString;
//    }
//    else if(select=='myNumber'){
//      if(set!=undefined) myNumber = set;
//      else return myNumber;
//    }
//    else return null;
// }

Вы всегда можете получить значение от main.js даже значение было изменено..

Переменная, объявленная с ключевым словом var или без него, была присоединена к глобальному объекту. Это основа для создания глобальных переменных в Node путем объявления переменных без ключевого слова var. В то время как переменные, объявленные с ключевым словом var, остаются локальными для модуля.

см. эту статью для дальнейшего понимания - https://www.hacksparrow.com/global-variables-in-node-js.html

Не новый подход, но немного оптимизированный. Создайте файл с глобальными переменными и поделитесь ими export и require. В этом примере Getter и Setter являются более динамичными, и глобальные переменные могут быть доступны только для чтения. Чтобы определить больше глобальных объектов, просто добавьте их в globals объект.

global.js

      const globals = {
  myGlobal: {
    value: 'can be anytype: String, Array, Object, ...'
  },
  aReadonlyGlobal: {
    value: 'this value is readonly',
    protected: true
  },
  dbConnection: {
    value: 'mongoClient.db("database")'
  },
  myHelperFunction: {
    value: function() { console.log('do help') }
  },
}

exports.get = function(global) {
  // return variable or false if not exists
  return globals[global] && globals[global].value ? globals[global].value : false;
};

exports.set = function(global, value) {
  // exists and is protected: return false
  if (globals[global] && globals[global].protected && globals[global].protected === true)
    return false;
  // set global and return true
  globals[global] = { value: value };
  return true;
};

примеры для получения и установки в any-other-file.js

      const globals = require('./globals');

console.log(globals.get('myGlobal'));
// output: can be anytype: String, Array, Object, ...

globals.get('myHelperFunction')();
// output: do help

let myHelperFunction = globals.get('myHelperFunction');
myHelperFunction();
// output: do help

console.log(globals.set('myGlobal', 'my new value'));
// output: true
console.log(globals.get('myGlobal'));
// output: my new value

console.log(globals.set('aReadonlyGlobal', 'this shall not work'));
// output: false
console.log(globals.get('aReadonlyGlobal'));
// output: this value is readonly

console.log(globals.get('notExistingGlobal'));
// output: false

С другим мнением, я думаю, global переменные могут быть лучшим выбором, если вы собираетесь опубликовать свой код в npmПотому что вы не можете быть уверены, что все пакеты используют один и тот же выпуск вашего кода. Так что если вы используете файл для экспорта singleton объект, это вызовет проблемы здесь.

Ты можешь выбрать global, require.main или любые другие объекты, которые являются общими для файлов.

Пожалуйста, скажите мне, если есть какие-то лучшие решения.

Если целью является браузер (путем связывания кода Node через Parcel.js или аналогичного), вы можете просто установить свойства наwindowобъект, и они становятся глобальными переменными:

      window.variableToMakeGlobal = value;

Затем вы можете получить доступ к этой переменной из всех модулей (и вообще из любого контекста Javascript).

Другие вопросы по тегам