値渡しとJavaScriptの参照渡し

JavaScriptを初めて使用する場合は、この言語が提供しなければならない面白い動作のいくつかに既に遭遇している可能性があ 最初は、これらの奇妙な癖はばかげてイライラするように見えるかもしれませんが、私はその狂気のすべての背後にある方法があることを約束し

私の謙虚な意見では、克服するのが最も難しいハードルの1つは、値渡しと参照渡しの違いです。 なぜこの概念はとても難しいのですか? まず第一に、JavaScriptがプリミティブ値や参照値とどのように相互作用するかを実際に理解することなく、かなり遠くに行くことができます。 これは、多くの場合、追跡するのが難しく、修正するのが面倒なバグのトンになる可能性があります。 第二に、これは技術的なインタビューで出てくる概念なので、それを理解していないことはあなたに対する巨大な赤い旗として数えられます。

恐れないで、仲間の読者! 教育を始めましょう…

プリミティブデータ型

JavaScriptでは、データ型をプリミティブデータ型とオブジェクトの二つの異なるバケットに分割することができます。

プリミティブデータ型、または値、およびオブジェクト型、または参照値を示すチャート

JavaScriptには六つのプリミティブデータ型があります: string, number, boolean, undefined, null, そしてsymbolはES6の時点で。

プリミティブデータ型は、値によって渡されるか、またはコピーされ、不変であり、既存の値を配列またはオブジェクトのように変更することはできません。 以下のコードを見て、これが実際に行われていることを見てみましょう。

を使用して作成jsbin.com

ここでは、x = 10y = xの二つの変数を作成しました。 10は数値でプリミティブな値なので、y = xを設定すると、実際には値、つまり10をコピーし、yに割り当てます。 また、以下のグラフを使用してこれを視覚化することもできます。

もしxの値を変更すると、y10の値を保持していることがわかります。 繰り返しになりますが、これはプリミティブ値がコピーされるため、yの値はxの値とは独立しているためです。 写真のコピーを作ると考えてください。 コピーを作成した後、あなたは2つの同一の写真を持っています:オリジナルとファクシミリ。 あなたが半分にオリジナルをカットした場合、唯一のオリジナルが変更され、ファクシミリはまったく同じままになります。

xの値を上書きしましたが、yは同じままです

参照オブジェクト

オブジェクトは、一方、参照渡しされ、値自体ではなく、値のメモリ内の場所を指 私たちのコードでこれを見てみましょう。

変数xとyはプリミティブデータ型

ではなくオブジェクトを指すようになりましたこの例では、x{dog: "poodle"}を指すオブジェクトになりました。 変数yを作成してxの値を割り当てると、dogの値を含むxのさまざまなプロパティ、つまり"poodle"を利用できるようになりました。 これはプリミティブ値に使用されるロジックとまったく同じように思えますが、以下の便利なチャートを見て、微妙で重要な違いを見てみましょう。

xとyの両方が、オブジェクトへの参照を格納するメモリ内の(構成された)アドレスを指しています

このチャートは、変数xyがプリミティブデータ型を このバージョンでは、xyの両方の値がデータ型ではなく、メモリ内のアドレスへの参照であり、実際には同じアドレスであることがわかります。 ここで、sizeの新しいプロパティをxに追加すると、xに何が起こるかを見てみましょうy

x まだオブジェクトを返しますが、今ではsizeの追加プロパティもあります! 繰り返しになりますが、これはxyの両方が同じ参照オブジェクトを指しているため、1つの変数に加えられた変更は他の変数でも表示されます。

チャートは、yの変化がx

と共有されている参照値を更新する方法を示していますこの概念を覚えておくために、私は参照値を家として、変数をその家に住 住民(変数)のすべては、”私は家を持っている”と言うと、同じ家を指すことができます。 単一の居住者は、彼らが家を黄色にペイントしたいと決定した場合、それが共有されているため、すべての住民は今、黄色の家を持っています。

さまざまな参照オブジェクトを含むもう一つの例を見てみましょう。

このコードでは、nameage、およびhobbiesのプロパティを含む変数personから始めます。 このオブジェクトをコンソールに出力すると、ちょうど作成したオブジェクトと同じように、期待どおりのものが得られます。

次に、changePersonという関数があり、引数を取り、いくつかの変更を加えてからオブジェクトを返します。 変数thirdPersonを作成すると、personの元のオブジェクトをその中に渡してchangePerson関数を呼び出します。 興味深いのは、コンソールthirdPersonpersonに再び印刷するときに何が起こるかです。

console.log(thirdPerson)は新しいプロパティを持つ新しいオブジェクト全体を返すことに注意してください。 今度はconsole.log(person)が返すものを見てください。 これは元のオブジェクトに似ていますが、changePerson関数で導入された新しいプロパティ値が含まれています。

等価性のチェック

最後に、プリミティブデータ型と参照オブジェクトが等価演算子でどのように動作するかを見てみましょう。

プリミティブデータ型に関しては、値が同じである限り、=記号の右側に何があるかは問題ではありません。 上記の変数abでは、異なる方法で記述されていますが、厳密な等価演算子である===を使用すると同じ値に評価されます。

第二の例では、dogcatの反対が当てはまります。 同じ値が含まれているように見えるかもしれませんが、は配列であり、参照オブジェクトであり、===dogcatの両方がメモリ内の値への同じ参照を持っているかどうかをチェックしていることを意味します。 一方、bird === dogは同じ参照オブジェクトを共有するためtrueです。

dogとbirdは同じ参照を共有しますが、catは同じ配列

結論

を持っているにもかかわらず、pass by value vs pass by referenceを導入しました。 参照が上書きまたは失われたときに何が起こるか、参照をコピーして新しいオブジェクトを作成し、コピーが深いコピーであることを確認する方法など、こ 私はより詳細にこれらの追加のトピックのいくつかに入るん以下で使用されるリソースをチェックアウトすることをお勧めします。

コメントを残す

メールアドレスが公開されることはありません。