JavaScriptを初めて使用する場合は、この言語が提供しなければならない面白い動作のいくつかに既に遭遇している可能性があ 最初は、これらの奇妙な癖はばかげてイライラするように見えるかもしれませんが、私はその狂気のすべての背後にある方法があることを約束し
私の謙虚な意見では、克服するのが最も難しいハードルの1つは、値渡しと参照渡しの違いです。 なぜこの概念はとても難しいのですか? まず第一に、JavaScriptがプリミティブ値や参照値とどのように相互作用するかを実際に理解することなく、かなり遠くに行くことができます。 これは、多くの場合、追跡するのが難しく、修正するのが面倒なバグのトンになる可能性があります。 第二に、これは技術的なインタビューで出てくる概念なので、それを理解していないことはあなたに対する巨大な赤い旗として数えられます。
恐れないで、仲間の読者! 教育を始めましょう…
プリミティブデータ型
JavaScriptでは、データ型をプリミティブデータ型とオブジェクトの二つの異なるバケットに分割することができます。
JavaScriptには六つのプリミティブデータ型があります: string
, number
, boolean
, undefined
, null
, そしてsymbol
はES6の時点で。
プリミティブデータ型は、値によって渡されるか、またはコピーされ、不変であり、既存の値を配列またはオブジェクトのように変更することはできません。 以下のコードを見て、これが実際に行われていることを見てみましょう。
ここでは、x = 10
とy = x
の二つの変数を作成しました。 10
は数値でプリミティブな値なので、y = x
を設定すると、実際には値、つまり10
をコピーし、y
に割り当てます。 また、以下のグラフを使用してこれを視覚化することもできます。
もしx
の値を変更すると、y
は10
の値を保持していることがわかります。 繰り返しになりますが、これはプリミティブ値がコピーされるため、y
の値はx
の値とは独立しているためです。 写真のコピーを作ると考えてください。 コピーを作成した後、あなたは2つの同一の写真を持っています:オリジナルとファクシミリ。 あなたが半分にオリジナルをカットした場合、唯一のオリジナルが変更され、ファクシミリはまったく同じままになります。
参照オブジェクト
オブジェクトは、一方、参照渡しされ、値自体ではなく、値のメモリ内の場所を指 私たちのコードでこれを見てみましょう。
ではなくオブジェクトを指すようになりましたこの例では、x
は{dog: "poodle"}
を指すオブジェクトになりました。 変数y
を作成してx
の値を割り当てると、dog
の値を含むx
のさまざまなプロパティ、つまり"poodle"
を利用できるようになりました。 これはプリミティブ値に使用されるロジックとまったく同じように思えますが、以下の便利なチャートを見て、微妙で重要な違いを見てみましょう。
このチャートは、変数x
とy
がプリミティブデータ型を このバージョンでは、x
とy
の両方の値がデータ型ではなく、メモリ内のアドレスへの参照であり、実際には同じアドレスであることがわかります。 ここで、size
の新しいプロパティをx
に追加すると、x
に何が起こるかを見てみましょうy
…
x
まだオブジェクトを返しますが、今ではsize
の追加プロパティもあります! 繰り返しになりますが、これはx
とy
の両方が同じ参照オブジェクトを指しているため、1つの変数に加えられた変更は他の変数でも表示されます。
と共有されている参照値を更新する方法を示していますこの概念を覚えておくために、私は参照値を家として、変数をその家に住 住民(変数)のすべては、”私は家を持っている”と言うと、同じ家を指すことができます。 単一の居住者は、彼らが家を黄色にペイントしたいと決定した場合、それが共有されているため、すべての住民は今、黄色の家を持っています。
さまざまな参照オブジェクトを含むもう一つの例を見てみましょう。
このコードでは、name
、age
、およびhobbies
のプロパティを含む変数person
から始めます。 このオブジェクトをコンソールに出力すると、ちょうど作成したオブジェクトと同じように、期待どおりのものが得られます。
次に、changePerson
という関数があり、引数を取り、いくつかの変更を加えてからオブジェクトを返します。 変数thirdPerson
を作成すると、person
の元のオブジェクトをその中に渡してchangePerson
関数を呼び出します。 興味深いのは、コンソールthirdPerson
とperson
に再び印刷するときに何が起こるかです。
console.log(thirdPerson)
は新しいプロパティを持つ新しいオブジェクト全体を返すことに注意してください。 今度はconsole.log(person)
が返すものを見てください。 これは元のオブジェクトに似ていますが、changePerson
関数で導入された新しいプロパティ値が含まれています。
等価性のチェック
最後に、プリミティブデータ型と参照オブジェクトが等価演算子でどのように動作するかを見てみましょう。
プリミティブデータ型に関しては、値が同じである限り、=
記号の右側に何があるかは問題ではありません。 上記の変数a
とb
では、異なる方法で記述されていますが、厳密な等価演算子である===
を使用すると同じ値に評価されます。
第二の例では、dog
とcat
の反対が当てはまります。 同じ値が含まれているように見えるかもしれませんが、は配列であり、参照オブジェクトであり、
===
はdog
とcat
の両方がメモリ内の値への同じ参照を持っているかどうかをチェックしていることを意味します。 一方、bird === dog
は同じ参照オブジェクトを共有するためtrueです。
結論
を持っているにもかかわらず、pass by value vs pass by referenceを導入しました。 参照が上書きまたは失われたときに何が起こるか、参照をコピーして新しいオブジェクトを作成し、コピーが深いコピーであることを確認する方法など、こ 私はより詳細にこれらの追加のトピックのいくつかに入るん以下で使用されるリソースをチェックアウトすることをお勧めします。