Автоматическое распространение ключей объекта на переменные - PullRequest
0 голосов
/ 10 октября 2019

У меня есть объект с серией пар ключ / значение. Я хотел бы распространить их все так:

const { 
    filterTarget, 
    filter, 
    source, 
    minDate,
    maxDate, 
    skip, 
    limit,
    tracking,
    trackingList,
    sortBy,
    sortOrder
} = req.body;

Есть ли для меня более быстрый способ сделать это, чтобы мне не приходилось писать ВСЕ имена свойств, но я мог бы скореепросто разложить их автоматически? Например:

SOMETHING_THAT_ASSIGNS_KEYS_TO_CONSTANTS = req.body;

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

Ответы [ 2 ]

2 голосов
/ 10 октября 2019

Вы не можете сделать это, не назначив объект window, чего вам следует избегать:

const obj = {
  filterTarget: "filterTarget value",
  filter: "filter value",
  source: "source value"
};

Object.entries(obj).forEach(([k, v]) => (window[k] = v));

console.log('filterTarget : ', filterTarget);

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

function applyFilter(obj) {
  Object.entries(obj).forEach(([k, v]) => (window[k] = v));  

  //using the expected values
  console.log(
    "Applying filter:", filter, 
    "\nsource", source,
    "\nfilterTarget", filterTarget)
}

/* time passes and  project changes */

//using the function with different values
applyFilter({
  target: "filterTarget value", //filterTarget was renamed
  filter: "filter value",
  source: "source value"
});

Во-вторых, если ваш объект использует все, что существует в window, глобальное значение будет перезаписано, что может привести к ошибкам. Хуже того, вы можете никогда не заметить ошибку, потому что функциональность может быть использована другим фрагментом кода или даже сторонней библиотекой. В худшем случае это может выглядеть так:

function useObject(obj) {
  Object.entries(obj).forEach(([k, v]) => (window[k] = v));  
  
  var c;
  if (atob) {
    c = b + a;
  } else {
    c = a + b;
  }
  
  return c;
}

//using the function with different values
var result = useObject({
  a: "hello",
  b: "world",
  atob: false
});

console.log("result", result);

/* third party code */

var base64Encoded = "REVBREJFRUY=";

var decoded = atob(base64Encoded); //error because it was overwritten

Проблема в том, что это может потенциально перезаписать что угодно - например, Array или Date, что может привести к поломке большого количества вашего кода. Но это еще более коварно с чем-то вроде atob, который, хотя и не "неясен", не показывает ЭТО много. Тем не менее, он может быть легко использован сторонним кодом или совершенно другой частью приложения, и он может случайно произойти сбой.

Имея это в виду, лучше переместить свойства объекта с более коротким именем:

const verylongnameobject = {
  filterTarget: "filterTarget value",
  filter: "filter value",
  source: "source value"
};

const obj = {};

Object.entries(verylongnameobject).forEach(([k, v]) => (obj[k] = v));

// OR
// const {...obj} = verylongnameobject;

console.log('filterTarget : ', obj.filterTarget);
0 голосов
/ 10 октября 2019

Невозможно динамически создавать константы на уровне области, но это можно сделать на уровне объекта, используя Object.defineProperty():

'use strict'

function createConstants(source) {
  const result = {};

  for (const [key, value] of Object.entries(source)) {
    Object.defineProperty(result, key, {
      value: value,
      enumerable: true,
      configurable: true,
      writable: false
    });
  }

  return result;
}

const a = createConstants({
  filterTarget: 42,
  filter: 43,
  source: 44,
});

console.log(a);

// Throws in 'strict' mode, because members of a are constants
a.source = 0;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...