Как сделать деструктурирующее присваивание множеству переменных более высокого уровня? - PullRequest
1 голос
/ 25 апреля 2020

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

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

let {
    numToRead,
    numConcurrent,
    numWorkers,
    skipParsing,
    preOpenFiles,
    dir: sourceDir,
    binary: doBinary,
} = processArgs(spec);

Этот код выполняется, когда мой модуль запускается как модуль верхнего уровня, и считывает его аргументы непосредственно из командной строки (processArgs() анализирует командную строку). Но теперь мне нужно изменить код так, чтобы этот код выполнялся условно (он находится внутри блока if), и иногда аргументы передаются через объект параметров в экспортируемой функции.

Итак, я начал чтобы написать это:

// if executed directly from the command line, get options from the command line
if (require.main === module) {

    // module level configuration variables from command line arguments (with defaults)
    let {
        numToRead,
        numConcurrent,
        numWorkers,
        skipParsing,
        preOpenFiles,
        dir: sourceDir,
        binary: doBinary,
    } = processArgs(spec);

    // more code here
}

module.exports = function(options) {
    // run this from options passed in by another module, rather than the command line
    // this code also needs to populate the same top level module variables
}

Но этот блок if создает все эти переменные внутри области видимости блока, а это не то, что мне нужно. Мне нужно, чтобы они были на верхнем уровне модуля.

Есть ли способ автоматически создать эти переменные на верхнем уровне модуля, когда назначение деструктурирования находится внутри блока без необходимости повторения определения всех переменных верхнего уровня?


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

// top level module arguments
let numToRead = 0,
    numConcurrent = 4,
    numWorkers = 5,
    skipParsing = false,
    preOpenFiles = "false",
    sourceDir = "./buckets",
    doBinary = false;

function run(options) {
    // load arguments into top level module variables
    ({
        numToRead,
        numConcurrent,
        numWorkers,
        skipParsing,
        preOpenFiles,
        dir: sourceDir,
        binary: doBinary,
    } = options);

    analyzeWithWorkers().catch(err => {
        console.log(err);
        process.exit(1);
    });
}

// for running from the command line
if (require.main === module) {
    run(processArgs(spec));
}

// for calling this from another module
module.exports = function(options) {
    // have to fill in any missing arguments
    // here as all options are optional
    let fullOptions = Object.assign({
        numToRead,
        numConcurrent,
        numWorkers,
        skipParsing,
        preOpenFiles,
        dir: sourceDir,
        binary: doBinary}, options);
    run(fullOptions);
}

Ответы [ 2 ]

1 голос
/ 25 апреля 2020

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

function main(options) {
  const {
    numToRead = 0,
    numConcurrent = 4,
    numWorkers = 5,
    skipParsing = false,
    preOpenFiles = "false",
    dir: sourceDir = "./buckets",
    binary: doBinary = false
  } = options;
  function analyzeWithWorkers() {
    // reference variables here
    // ...
  }
  // initialize other functions if needed, referencing those variables
  analyzeWithWorkers().catch(err => {
      console.log(err);
      process.exit(1);
  });
}
if (require.main === module) {
  main(processArgs(spec));
}
module.exports = main;

function main(options) {
  const {
    numToRead = 0,
    numConcurrent = 4,
    numWorkers = 5,
    skipParsing = false,
    preOpenFiles = "false",
    dir: sourceDir = "./buckets",
    binary: doBinary = false
  } = options;
  function analyzeWithWorkers() {
    console.log(skipParsing, sourceDir);
    return Promise.resolve();
  }
  // initialize other functions if needed, referencing those variables
  analyzeWithWorkers().catch(err => {
      console.log(err);
      process.exit(1);
  });
}
/*
if (require.main === module) {
  main(processArgs(spec));
}
module.exports = main;
*/
main({});
main({ dir: 'someDir' });

Если переменные должны быть определены на верхнем уровне, нет никакого способа повторить их все хотя бы дважды - один раз объявить сверху уровень, и один раз, чтобы возможно переназначить внутри экспортируемой функции. Вы можете превратить ваши 3 повторения в 2 повторения, назначив значения по умолчанию внутри run, экспортируемой функции, которая присваивает внешние переменные (при условии, что модуль всегда вызывается извне либо из командной строки, либо из основной экспортируемой функции). ).

let numToRead,
    numConcurrent,
    numWorkers,
    skipParsing,
    preOpenFiles,
    sourceDir,
    doBinary;

function run(options) {
    // load arguments into top level module variables
    ({
        numToRead = 0,
        numConcurrent = 4,
        numWorkers = 5,
        skipParsing = false,
        preOpenFiles = "false",
        dir: sourceDir = "./buckets",
        binary: doBinary = false
    } = options);
    analyzeWithWorkers().catch(err => {
        console.log(err);
        process.exit(1);
    });
}

function analyzeWithWorkers() {
    console.log(skipParsing, sourceDir);
    return Promise.resolve();
}
if (require.main === module) {
  run(processArgs(spec));
}
module.exports = run;

let numToRead,
    numConcurrent,
    numWorkers,
    skipParsing,
    preOpenFiles,
    sourceDir,
    doBinary;
    
function run(options) {
    // load arguments into top level module variables
    ({
        numToRead = 0,
        numConcurrent = 4,
        numWorkers = 5,
        skipParsing = false,
        preOpenFiles = "false",
        dir: sourceDir = "./buckets",
        binary: doBinary = false
    } = options);
    analyzeWithWorkers().catch(err => {
        console.log(err);
        process.exit(1);
    });
}

function analyzeWithWorkers() {
    console.log(skipParsing, sourceDir);
    return Promise.resolve();
}
run({});
run({ dir: 'someDir' });
0 голосов
/ 25 апреля 2020

Вы можете использовать две вещи вместе. Object.assign() и разрушение может быть пройдено.

function init() {
      let obj = {prop1, prop2} = getValues();
      Object.assign(globalThis, obj);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...