自动将对象键传播到变量

Automatically Spreading Object Keys to Variables

我有一个包含一系列 key/value 对的对象。我想像这样将它们全部展开:

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

我是否有更快的方法来执行此操作,这样我就不必写下所有 属性 名称,而是可以自动将它们展开?喜欢:

SOMETHING_THAT_ASSIGNS_KEYS_TO_CONSTANTS = req.body;

最后,我需要相同的结果,但如果不是完全必要,我不想写出所有变量。

如果不将 分配给 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

问题是这可能会覆盖任何内容 - 例如 ArrayDate,这会破坏您的很多代码。但是它甚至更阴险,像 atob 这样的东西,虽然 "obscure" 没有出现那么多。但是,它很容易被第三方代码或应用程序的完全不同的部分使用,并且会随机失败。

考虑到这一点,最好将属性移动到名称较短的对象中:

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);

无法在范围级别动态创建常量,但可以使用 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;