最近の追加
これは言語に最近追加されたものです。 古いブラウザにはポリフィルが必要な場合があります。
オプションのチェーン?.
これは、中間プロパティが存在しない場合でも、ネストされたオブジェクトのプロパティにアクセスする安全な方法です。
チュートリアルを読んで JavaScript を学び始めたばかりの場合は、まだこの問題に気付いていないかもしれませんが、この問題は非常に一般的なものです。
例として、ユーザーに関する情報を保持するuser
オブジェクトがあるとします。
ほとんどのユーザーは、 user.address
プロパティに番地user.address.street
を含むアドレスを持っていますが、それらを提供していないユーザーもいます。
このような場合、 user.address.street
取得しようとして、ユーザーにアドレスがない場合、エラーが発生します。
ユーザー = {} にします。 // 「アドレス」プロパティを持たないユーザー アラート(ユーザー.アドレス.ストリート); // エラー!
それは予想通りの結果です。 JavaScript は次のように動作します。 user.address
がundefined
あるため、 user.address.street
を取得しようとすると、エラーが発生して失敗します。
実際の多くの場合、ここではエラー (「通りがありません」という意味) ではなく、 undefined
取得することを好みます。
…そして別の例。 Web 開発では、 document.querySelector('.elem')
などの特別なメソッド呼び出しを使用して Web ページ要素に対応するオブジェクトを取得できますが、そのような要素がない場合はnull
を返します。
// document.querySelector('.elem') 要素がない場合は null let html = document.querySelector('.elem').innerHTML; // nullの場合はエラー
もう一度言いますが、要素が存在しない場合は、 null
の.innerHTML
プロパティにアクセスするとエラーが発生します。また、場合によっては、要素が存在しないのが正常である場合、エラーを回避し、結果としてhtml = null
そのまま受け入れたいことがあります。
どうすればこれができるでしょうか?
明らかな解決策は、 if
または条件演算子?
を使用して値をチェックすることです。 、そのプロパティにアクセスする前に、次のようにします。
ユーザー = {} にします。 アラート(ユーザー.アドレス ? ユーザー.アドレス.番地 : 未定義);
正常に動作し、エラーはありません…しかし、非常に洗練されていません。ご覧のとおり、コード内に"user.address"
2 回現れています。
同じことがdocument.querySelector
でどのように見えるかは次のとおりです。
let html = document.querySelector('.elem') ? document.querySelector('.elem').innerHTML : null;
ここでは、要素検索document.querySelector('.elem')
が実際に 2 回呼び出されていることがわかります。良くない。
より深くネストされたプロパティの場合、より多くの繰り返しが必要になるため、さらに醜くなります。
たとえば、同様の方法でuser.address.street.name
を取得してみましょう。
ユーザー = {} にします。 // ユーザーにはアドレスがありません alert(user.address ? user.address.street ? user.address.street.name : null : null);
これはひどいことであり、そのようなコードを理解するのが困難になる可能性さえあります。
&&
演算子を使用して、もう少し良い書き方があります。
ユーザー = {} にします。 // ユーザーにはアドレスがありません alert( user.address && user.address.street && user.address.street.name ); // 未定義 (エラーなし)
プロパティへのパス全体を AND 演算すると、すべてのコンポーネントが存在することが保証されます (存在しない場合、評価は停止します)。ただし、これも理想的ではありません。
ご覧のとおり、コード内ではプロパティ名がまだ重複しています。たとえば、上記のコードでは、 user.address
3 回現れます。
これが、オプションのチェーン?.
言語に追加されました。この問題をきっぱり解決するために!
オプションのチェーン?.
?.
はundefined
またはnull
であり、 undefined
を返します。
さらにこの記事では、簡潔にするために、 null
およびundefined
でない場合に、何かが「存在する」とします。
つまり、 value?.prop
:
value
存在する場合は、 value.prop
として機能します。
それ以外の場合 ( value
がundefined/null
場合)、 undefined
を返します。
? を使用してuser.address.street
にアクセスする安全な方法は次のとおりです?.
:
ユーザー = {} にします。 // ユーザーにはアドレスがありません アラート( ユーザー?.アドレス?.ストリート ); // 未定義 (エラーなし)
コードは短くてきれいで、重複はまったくありません。
document.querySelector
を使用した例を次に示します。
let html = document.querySelector('.elem')?.innerHTML; // 要素がない場合は未定義になります
user?.address
を使用したアドレスの読み取りは、 user
オブジェクトが存在しない場合でも機能します。
ユーザー = null にします。 アラート( ユーザー?.アドレス ); // 未定義 アラート( ユーザー?.アドレス. ストリート ); // 未定義
注意してください: ?.
構文では、その前の値はオプションになりますが、それ以降はオプションになりません。
たとえば、 user?.address.street.name
には?.
user
安全にnull/undefined
にすることを許可します (その場合はundefined
を返します)。ただし、それはuser
に対してのみです。その他のプロパティには通常の方法でアクセスします。それらの一部をオプションにしたい場合は、さらに多くの を置き換える必要があります.
と?.
。
オプションのチェーンを使いすぎないでください
?.
何かが存在しなくても大丈夫な場合にのみ。
たとえば、コード ロジックに従ってuser
オブジェクトが存在する必要があるが、 address
オプションである場合は、 user user.address?.street
ではなくuser?.address?.street
と記述する必要があります。
その後、 user
たまたま未定義の場合、それに関するプログラミング エラーが表示され、修正されます。そうでなければ、 ?.
、コーディング エラーが適切でない場合は沈黙する可能性があり、デバッグがより困難になります。
?.
宣言しなければならない
変数user
まったくない場合、 user?.anything
エラーをトリガーします。
// ReferenceError: ユーザーが定義されていません ユーザー?.アドレス;
変数は宣言する必要があります ( let/const/var user
または関数パラメータとしてなど)。オプションのチェーンは、宣言された変数に対してのみ機能します。
前にも言われたように、 ?.
左側の部分が存在しない場合は、評価を直ちに停止 (「短絡」) します。
したがって、 ?.
、作られません。
例えば:
ユーザー = null にします。 x = 0 とします。 ユーザー?.sayHi(x++); // "user" がないため、実行は SayHi 呼び出しと x++ に到達しません。 アラート(x); // 0、値はインクリメントされません
オプションのチェーン?.
は演算子ではなく、関数や角括弧でも機能する特別な構文構造です。
たとえば、 ?.()
存在しない可能性のある関数を呼び出すために使用されます。
以下のコードでは、一部のユーザーはadmin
メソッドを持っていますが、一部のユーザーは持っていません。
userAdmin = { にします 管理者() { alert("私は管理者です"); } }; userGuest = {}; にします。 userAdmin.admin?.(); // 私は管理者です userGuest.admin?.(); // 何も起こりません (そのようなメソッドはありません)
ここでは、どちらの行でも、最初にドット ( userAdmin.admin
) を使用してadmin
プロパティを取得しています。これは、 user
オブジェクトが存在すると想定しているため、安全に読み取ることができます。
次に、 ?.()
左側の部分をチェックします。 admin
関数が存在する場合は、それが実行されます ( userAdmin
も同様です)。それ以外の場合 ( userGuest
の場合)、評価はエラーなしで停止します。
?.[]
構文は、ドットの代わりに大括弧[]
使用してプロパティにアクセスする場合にも機能します.
。前のケースと同様に、存在しない可能性のあるオブジェクトからプロパティを安全に読み取ることができます。
let key = "名"; user1 = { にします 名前:「ジョン」 }; user2 = null にします。 アラート( user1?.[キー] ); // ジョン アラート( user2?.[キー] ); // 未定義
?.
delete
あり:
ユーザーを削除しますか?.名前; // ユーザーが存在する場合は user.name を削除します
?.
安全な読み取りと削除のためですが、書き込みはできません
オプションのチェーン?.
代入の左側には使用できません。
例えば:
ユーザー = null にします。 user?.name = "ジョン"; // エラーが発生し、動作しません // 評価結果が次のようになるため: unknown = "John"
オプションのチェーン?.
構文には 3 つの形式があります。
obj?.prop
– obj
が存在する場合はobj.prop
を返し、それ以外の場合はundefined
を返します。
obj?.[prop]
– obj
が存在する場合はobj[prop]
を返し、それ以外の場合はundefined
を返します。
obj.method?.()
– obj.method
が存在する場合はobj.method()
を呼び出し、存在しない場合はundefined
を返します。
ご覧のとおり、それらはすべて簡単で使いやすいです。 ?.
左側の部分がnull/undefined
かどうかをチェックし、そうでない場合は評価を続行します。
?.
ネストされたプロパティに安全にアクセスできるようになります。
それでも、 ?.
コードロジックに従って、左側の部分が存在しないことが許容される場合にのみ、注意してください。プログラミングエラーが発生した場合でも、それが隠蔽されないようにするためです。