Help us understand the problem. What is going on with this article?

【JavaScript】関数の引数をオブジェクト形式にして、さらに初期値を設定する。

More than 1 year has passed since last update.

JavaScriptの関数に引数が複数ある場合、オブジェクト形式にすると、値の意味がわかりやすくてとても便利です。
さらに、引数に初期値を設定してあげれば、関数の設定を変えたいときだけ引数を書けば良いので、より便利に関数を使うことができます。

const func = ({ hoge = 'foo' } = {}) => console.log(hoge);

func(); // 'foo'
func({ hoge: 'bar' }); // 'bar'

こんな感じ。

関数func()の実引数を空にしたときは、コンソールログに文字列fooが表示され、オブジェクト形式でhogeプロパティの値を設定すると、そのプロパティ値が適用されるので、文字列barが表示されます。

便利ですね。

でも、なぜこのような挙動になるのでしょうか??

分割代入でオブジェクトの初期値を設定

const func = ({ hoge = 'foo' } = {}) => console.log(hoge);

上記関数の{hoge = 'foo'} = {}部分は、分割代入の記法を使用しています。
分割代入のサンプルっぽく、引数の中身を独立させてみます。

const obj = {};
const { hoge = 'foo' } = obj;
// const { hoge = 'foo' } = {}; と同じ

console.log(obj.hoge) // undefined
console.log(hoge); // 'foo'

オブジェクトの分割代入では、左辺を{ hoge = 'foo' }の形にすることで、初期値を設定できます。
また、右辺のオブジェクトのプロパティがundefinedの場合は、左辺の初期値が適用されるので、hogeの値は文字列fooになります。

もし、右辺のオブジェクトのプロパティに値があった場合は、そちらが適用されるので、以下のようにhogeの値が文字列barになります。

const obj = { hoge: 'bar' };
const { hoge = 'foo' } = obj;
// const { hoge = 'foo' } = { hoge: 'bar' }; と同じ

console.log(obj.hoge) // 'bar'
console.log(hoge); // 'bar'

上記の内容を踏まえて、改めて関数を見てみましょう。

const func = ({ hoge = 'foo' } = {}) => console.log(hoge);

func(); // 'foo'
func({ hoge: 'bar' }); // 'bar'

実引数が空の場合は、仮引数の{ hoge = 'foo' } = {}が適用され、hogeが文字列fooになります。
逆に、実引数にオブジェクトが指定されている場合、仮引数内は{ hoge = 'foo' } = { hoge: 'bar' }の状態になるので、hogeは文字列barになります。

ちなみに、仮引数の= {}を消してしまうと、実引数が空のときに代入元のオブジェクトがなくなってしまうので、エラーになってしまいます。

const func = ({ hoge = 'foo' }) => console.log(hoge);

func(); // Uncaught TypeError
func({}); // 'foo'
func({ hoge: 'bar' }); // 'bar'

オブジェクトの分割代入に関して

ここからは余談ですが、オブジェクトの分割代入を少し掘り下げてみます。

const obj = {};
const { hoge = 'foo' } = obj;

console.log(obj.hoge) // undefined
console.log(hoge); // 'foo'

オブジェクトobjhogeプロパティがundefinedの状態ということは、以下のように書き換えることができます。

const obj = { hoge: undefined };
const { hoge = 'foo' } = obj;

console.log(obj.hoge) // undefined
console.log(hoge); // 'foo'

さらに、左辺の{ hoge = 'foo' }は、オブジェクトのプロパティとプロパティ値が同じだから省略されていると考えられるため、

const obj = { hoge: undefined };
const { hoge: hoge = 'foo' } = obj;

console.log(obj.hoge) // undefined
console.log(hoge); // 'foo'

こう書き換えることもできます。
hoge ばっかりだと分かりづらいので、ちょっと変えてみます。

const obj = { hoge: undefined };
const { hoge: val = 'foo' } = obj;

console.log(obj.hoge) // undefined
console.log(val); // 'foo'

こうやってみると、プロパティ値の変数valに、文字列fooを代入しているようにみえますね。
つまり、オブジェクトの分割代入は、オブジェクトのプロパティ値を変数とし、そこに値を代入していると考えられるわけです。

const _val = 'foo';
const obj = { hoge: _val };
const val = obj.hoge;
console.log(val); // 'foo'

こんな感じで。

分割代入はなかなか理解しづらい記法ですが、こうやって紐解いてみるとわかりやすいですね。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした