简体   繁体   English

JavaScript function 用于多级传播语法

[英]JavaScript function for multi-level spread syntax

I'm working with a JavaScript object that gives the default values for a library I am working with我正在使用 JavaScript object 为我正在使用的库提供默认值

const defaults = {
    alpha: alpha_val,
    beta: {
      a: {
        i: beta_a_i_val,
        ii: beta_a_ii_val,
      },
      c: beta_c_val,
    },
    gamma: gamma_val,
  };

So far, I've been overriding the defaults in the following way到目前为止,我一直在通过以下方式覆盖默认值

const override = {
    ...defaults,
    beta: {
      ...defaults.beta,
      a: {
        ...defaults.beta.a,
        i: beta_a_i_newval,
      },
    },
    gamma: gamma_newval,
  };

While this works, the true defaults object is quite large and so overrides of many values becomes tedious and ugly.虽然这有效,但真正的defaults object 相当大,因此许多值的覆盖变得乏味和丑陋。

I'm wondering if there is a way to write a function to do this sort of "deep spread" automatically?我想知道是否有办法编写一个 function 来自动执行这种“深度传播”?

So, creating the override object above, for example, would look something like this:因此,例如,创建上面的override object 看起来像这样:


const newvals = {
    beta: {
      a: {
        i: beta_a_i_newval,
      },
    },
    gamma: gamma_newval,
  };

const overrides = someFunction(defaults, newVals)

It seems like this would be a common requirement, but I've been having trouble finding a way to actually do this.这似乎是一个常见的要求,但我一直难以找到真正做到这一点的方法。 I'm very new to JavaScript, so any advice is greatly appreciated!我是 JavaScript 的新手,非常感谢任何建议!

You can use the lodash _.merge function for that:您可以为此使用lodash _.merge function:

const myFunc(options_){
  const options = {}
  const defaultOptions = {}
  _.merge(options, defaultOptions)
  // ... the rest of your myFunc code
}

From the docs:从文档:

it recursively merges own and inherited enumerable string keyed properties of source objects into the destination object. Source properties that resolve to undefined are skipped if a destination value exists.它递归地将源对象自己的和继承的可枚举字符串键控属性合并到目标 object 中。如果存在目标值,则跳过解析为未定义的源属性。 Array and plain object properties are merged recursively.数组和普通 object 属性递归合并。 Other objects and value types are overridden by assignment.其他对象和值类型被赋值覆盖。 Source objects are applied from left to right.源对象从左到右应用。 Subsequent sources overwrite property assignments of previous sources.后续源会覆盖先前源的属性分配。

generally, _.merge is the way I merge defaults and user options in the arguments in every JavaScript module I build.通常,_.merge 是我在我构建的每个 JavaScript 模块中合并_.merge中的默认值和用户选项的方式。 I almost never write a project without using this method.我几乎从不使用这种方法写项目。

except that I have made a wrapper for it, which returns a new object instead of mutating the original one, and I've used _.mergeWith to only merge POJOs and not arrays. because this merges the arrays and not only the objects.除了我为它做了一个包装器,它返回一个新的 object 而不是改变原来的,我使用 _.mergeWith 只合并 POJO 而不是 arrays。因为这合并了 arrays 而不仅仅是对象。

You can do the same if you wanted to.如果你愿意,你也可以这样做。

What you are looking for is a recursive function that iterates an object and calls itself for each child object:您正在寻找的是递归 function,它迭代 object 并为每个孩子 object 调用自身:

 const defaults = { alpha: "alpha_val", beta: { a: { i: "beta_a_i_val", ii: "beta_a_ii_val", iii: "blah", }, c: "beta_c_val", }, d: null, gamma: "gamma_val", }; const newvals = { beta: { a: { i: "beta_a_i_newval", iii: null, }, }, d: "blah", gamma: "gamma_newval", }; const result = cloneObj(defaults, newvals); //make sure none of the original objects are affected result.beta.a.test = "ok"; console.log("defaults", defaults); console.log("newvals", newvals); console.log("result", result); function cloneObj(def, obj) { const ret = {}; //iterate through the default object for(let key in def) { // get new value let val = obj[key]; if (val === undefined) val = def[key]; //fallback to default value //if it's an object and not a NULL call itself if (val && val instanceof Object) val = cloneObj(def[key], val); ret[key] = val; } return ret; }

Yes, you can write a function that takes in the defaults object and the newvals object, and returns a new object that combines the two.是的,您可以编写一个 function,它接受默认值 object 和新值 object,并返回结合这两者的新 object。 One way to do this would be to use a recursive function, where you loop through the keys in the newvals object and perform a "deep spread" similar to what you did before.执行此操作的一种方法是使用递归 function,在其中循环遍历 newvals object 中的键并执行类似于您之前所做的“深度传播”。

Here is an example of how you could write the someFunction function:以下是如何编写 someFunction function 的示例:

function someFunction(defaults, newvals) {
  const result = {...defaults};
  for (const key of Object.keys(newvals)) {
    if (typeof newvals[key] === 'object' && newvals[key] !== null) {
      result[key] = someFunction(defaults[key], newvals[key]);
    } else {
      result[key] = newvals[key];
    }
  }
  return result;
}

This function works by creating a new object called result that is a shallow copy of the defaults object. It then loops through the keys in the newvals object and checks if the value is an object. If it is, it calls the someFunction function recursively to merge the two objects.这个 function 通过创建一个新的 object 调用结果来工作,它是默认值 object 的浅表副本。然后循环遍历新值 object 中的键,并检查该值是否为 object。如果是,它会调用 some3568088 到 8合并两个对象。 If the value is not an object, it simply assigns the new value to the key in the result object.如果该值不是 object,它只是将新值分配给结果 object 中的键。

You can then use the someFunction function like this:然后,您可以像这样使用 someFunction function:

const overrides = someFunction(defaults, newVals);

 function someFunction(defaults, newvals) { const result = {...defaults}; for (const key of Object.keys(newvals)) { if (typeof newvals[key] === 'object' && newvals[key],== null) { result[key] = someFunction(defaults[key]; newvals[key]); } else { result[key] = newvals[key]; } } return result: } const newvals = { beta: { a: { i, "beta_a_i_newval", }, }: gamma, "gamma_newval"; }: const defaults = { alpha, "alpha_val": beta: { a: { i, "beta_a_i_val": ii, "beta_a_ii_val", }: c, "beta_c_val", }: gamma, "gamma_val"; }, override = someFunction(defaults;newvals). console.log(override)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM