関数の引数にスプレッド構文を使った場合
背景
React書いていると以下のような...props
のような記述がたまに見られるが、どういう振る舞いになるのか少し混乱したから整理する。
const DeleteButton = ({className, ...props}) => ( <span className={[style.root, className].join(' ')} {...props}> <TrashCanIcon /> <Baloon>削除する</Baloon> </span> );
スプレッド構文
ドットを3つつなげたこれはスプレッド構文と呼ばれている。Iterableなオブジェクトの中身を展開してくれるようだ。
これらは以下の3つの場面で使うことができる。 1. 関数呼び出し 2. Arrayリテラル 3. Objectリテラル
2,3は想像が付くんだが関数呼び出しのときの振る舞いがうまく想像できない。
実験
とりあえず使ってみる。
const hage = ({...props}) => {console.log(props)}; hage({a:1}); // => {a: 1}
const hage=(props) => {console.log(props)};
と変わらないっぽい?
propsの中身を一度展開し、再度Objectにしたものをprops
という名前で束縛しているのか?
そもそも({a, b}) => {}
って引数に渡されたObjectからa
とb
のプロパティだけを抽出する構文だよね?なんかおかしくね?
const hige = ({...props}) => {console.log(a)}; hige({a: 1}); // => ReferenceError: a is not defined
これでa
に1
が束縛されるんじゃないかと思ったんだけどな…。
propsの中身を一度展開し、再度Objectにしたものを
props
という名前で束縛している?
これが正解っぽい
const huge = ({a, ...props}) => {console.log(a, props)}; huge({a: 1, b: 2, c: 3}); /// => (1, {b: 2, c: 3})
なるほど?...を付けたら問答無用で残りは引き渡ってくれるのかー。
結論
というわけで最初の例はなんでもごちゃごちゃに渡されてくるprops
からclassName
だけをチュ出し、残りの要素は再度props
に束縛するという感じか。納得はしてないが振る舞いはわかった。
再掲
const DeleteButton = ({className, ...props}) => ( <span className={[style.root, className].join(' ')} {...props}> <TrashCanIcon /> <Baloon>削除する</Baloon> </span> );