[英]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 問題,但現在您已經解決了,我相信問題是......
您有一個共享組件(可能是 React),它接受一個 function 屬性,用於允許調用者指定結果的一部分(即表格行)的呈現方式。 function 目前看起來像這樣(為清楚起見,Typescript 語法)
row: (entity: Entity) => JSX.Element
你想向渲染器引入一個新元素,包括一些元數據,但你想使用 object(而不是多個參數)來避免
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.