簡體   English   中英

如何知道 JavaScript function 接受一個簡單的參數或一個解構的 object?

[英]How to know a JavaScript function accepts a simple parameter or a destructured object?

考慮這兩個函數:

const render = (entity) => {
   // function body
}

const render = ({
    entity,
    isAdmin
}) => {
   // function body
}

現在假設我想調用這個 function。如果它接受一個解構的 object,我應該以不同的方式傳遞 arguments。

render({
    name: 'John', 
    age: 40
})

// or

render({
    entity: {
      name: 'John',
      age: 40
    },
    isAdmin: true
})

有沒有辦法讓我知道 function 是否接受解構的 object 作為其參數?

請注意,對於這兩個函數, render.length都返回 1。 arguments對我沒有幫助,因為它可以在 function 內部訪問,但不能在外部訪問。

更新

這是真實的場景。

我們有一個管理面板(類似於 React Admin),許多公司的 500 多個項目都在使用它。 您可以想象我們有成千上萬的列表要以表格格式顯示。

現在,對於每個表格,開發人員都會為我們提供一個render function,這是一個用於表格每一行的 React 組件。

這就是他們如何使用我們的<List />組件:

const Customers = () => {
    return <List
        // other props like title, headers, etc.
        row={entity => <>
             <td>{entity.name}</td>
        </>}
    />
}

我們不想強迫他們跨越數千個列表來編寫row={({entity, metadata}) => <><td>{entity.name}</td></>}

我不清楚為什么你需要這樣做。 function 的參數一旦聲明就不會也不能更改,在調用它之前,您應該始終知道 function 接受哪些參數。

但是,僅出於此目的,這里有一個您可以執行此操作的方法示例。 將 function 字符串化,然后使用正則表達式匹配參數列表中的({ })

 const render1 = (entity) => {} const render2 = ({ entity, isAdmin }) => {} const render3 = (arg) => someotherFunc({arg}) function doesDestructure(func){ return /\({.+}\) =>/gm.test(func.toString().replaceAll("\n", "")) } console.log(doesDestructure(render1)) console.log(doesDestructure(render2)) console.log(doesDestructure(render3))

或者適用於所有功能的版本:

 const render1 = (entity) => {} const render2 = ({ entity, isAdmin }) => {} const render3 = (entity) => subscribe(({entity}) => { }) function doesDestructure(func){ return /\({.+}\)/gm.test(func.toString().replaceAll("\n", "").split("=>")[0]) } console.log(doesDestructure(render1)) console.log(doesDestructure(render2)) console.log(doesDestructure(render3))

您最初的問題絕對是XY 問題,但現在您已經解決了,我相信問題是......

  1. 您有一個共享組件(可能是 React),它接受一個 function 屬性,用於允許調用者指定結果的一部分(即表格行)的呈現方式。 function 目前看起來像這樣(為清楚起見,Typescript 語法)

     row: (entity: Entity) => JSX.Element
  2. 你想向渲染器引入一個新元素,包括一些元數據,但你想使用 object(而不是多個參數)來避免

    1. 鎖定參數順序
    2. 鎖定參數數量
    row: (obj: MetaData & { entity: Entity }) => JSX.Element

為了挽救開發人員的理智,我建議引入一個新的回調道具,允許他們在需要時進行更改

type EntityMeta = MetaData & { entity: Entity };

interface ListProps {
  row?: (entity: Entity) => JSX.Element,
  rowWithMeta?: (row: EntityMeta) => JSX.Element,
}

在您的List組件中,您可以決定使用哪個渲染器

const rowRenderer = useCallback(
  (row: EntityMeta) => props.rowWithMeta?.(row) ?? props.row?.(row.entity),
  [props.rowWithMeta, props.row]
);

return (
  <table>
    {rows.map((row, i) => (
      <tr key={i}>{rowRenderer(row)}</tr>
    ))}
  </table>
);

就個人而言,您提到的關於上面第 2 點的問題與我無關。 我會簡單地構造你想要的任何元數據並將其作為第二個參數傳遞

row: (entity: Entity, meta: MetaData)

您可以根據需要處理第二個參數,只需將第一個參數保留為純粹的實體

return (
  <table>
    {rows.map(({ entity, ...meta }, i) => (
      <tr key={i}>{props.row(entity, meta)}</tr>
    ))}
  </table>
);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM