简体   繁体   中英

What's the best way of dealing with optional && dynamic function parameters in Javascript?

I am JS newbie and trying to figure out what's the smart way of handling this. This is my function that generates and returns an array (Please see the comments in the code below):

const getStylesArray = (noteBlockSettings, blockId, key, value) => {

    // ---------------------------------------------------
    // noteBlockSettings parameter will be passed to this function no matter what. 
    // So it is definetely not undefined.

    // NoteBlockSettings has bgOpacity, bgColor, primaryColor, secondaryColor, textColor keys and values.

    // key and value parameters of this function are optional, so they may be undefined or not.

    // ***** What i am trying to achieve is : *****
    // If key parameter is passed (can be bgOpacity, bgColor, primaryColor, secondaryColor, textColor)
    // use this passed parameter rather than the value in noteBlockSettings object. 
    // If key parameter is undefined, use the value in noteBlockSettings object.
    
    // ---------------------------------------------------

    let { bgColor, primaryColor, secondaryColor, bgOpacity, textColor } = noteBlockSettings

    if (key === 'bgColor') {
         bgColor = value
    }

    if (key === 'primaryColor') {
         primaryColor = value
    }

    if (key === 'secondaryColor') {
         secondaryColor = value
    }

    if (key === 'bgOpacity') {
         bgOpacity = value
    }

    if (key === 'textColor') {
         textColor = value
    }


    const stylesArray = [
         // Here i am using the variables defined above to dynamically generate the array
         // Like bgOpacity, bgColor, primaryColor, secondaryColor, textColor etc..
         {
              styleClass: '.head',
              styleValue: `background:${addAlpha(colord(bgColor).lighten(0.075).toHex(), bgOpacity)}; border-color:${addAlpha(colord(bgColor).darken(0.06).toHex(), bgOpacity)};`,
              styleTriggers: 'bgColor bgOpacity',
         },

         {
              styleClass: '.head .options .btn-icon',
              styleValue: `color:${addAlpha(colord(textColor), 0.4)};`,
              styleTriggers: 'textColor',
         },

         {
              styleClass: '.head .options .btn-icon:hover',
              styleValue: `color:${primaryColor};`,
              styleTriggers: 'primaryColor',
         },
         .
         .
         .
    ]

    // Finally returning the generated array 
    return stylesArray
}

This is working and it is just a primitive attempt. However I don't know how, but I feel like there should be much "smarter" way of handling this. So, my question is: What is the best and minimal way of achieving the same result?

Thank you !

You can build a "final" settings object before destructuring it. Then you don't need to check every variable:

// If `key` is passed and a valid key in the object, copy the object and overwrite
// the property. 
const finalSettings = key in noteBlockSettings ? 
   {...noteBlockSettings, [key]: value} :
   noteBockSettings;

const { bgColor, primaryColor, secondaryColor, bgOpacity, textColor } = finalSettings;
// ...

{...noteBlockSettings, [key]: value} basically copies noteBlockSettings and sets the property whose name is in key to value .

Having said that, I'm wondering why the call site simply doesn't pass the complete settings object. That would make the API clearer.

You can simply get a copy of the noteBlockSettings then extract each values in it.

  1. Copy the values by doing
let copy = {...original};
  1. Modify any key:
copy[key] = value;
  1. Extract the values like you did before
let {a, b, c, d, e, ...} = copy 

 const mutateStyles = (noteBlockSettings, blockId, key, value) => { // --------------------------------------------------- // noteBlockSettings parameter will be passed to this function no matter what. // So it is definetely not undefined. // NoteBlockSettings has bgOpacity, bgColor, primaryColor, secondaryColor, textColor keys and values. // key and value parameters of this function are optional, so they may be undefined or not. // ***** What i am trying to achieve is: ***** // If key parameter is passed (can be bgOpacity, bgColor, primaryColor, secondaryColor, textColor) // use this passed parameter rather than the value in noteBlockSettings object. // If key parameter is undefined, use the value in noteBlockSettings object. // --------------------------------------------------- let noteBlockSettingsCopy = {...noteBlockSettings} noteBlockSettingsCopy[key] = value; let { bgColor, primaryColor, secondaryColor, bgOpacity, textColor } = noteBlockSettingsCopy return noteBlockSettingsCopy; } let data = { bgColor: "#fff", primaryColor: '#0ff', secondaryColor: "#ff0", bgOpacity: "0.1", textColor: "#000" }; console.log(mutateStyles(data, 1, "bgColor", "#f0f"));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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