1

最近、JavaScript のオブジェクト指向プログラミングについて学び始めました。私が理解したのは、変数を参照するとき、実際には実際の値ではなく、メモリ内の場所を参照するということです。そのため、インスタンスをコピーすることになっているすべての " return this " メソッドが機能しません。

したがって、コード例:

//An example object with a simple property and
//failing "copy" function.
function MyObject()
{
    this.myProperty = 123;
    this.copy = function() { return this; };
}

var iOne = new MyObject();
var iTwo = iOne.copy();
iTwo.myProperty = 321;

「copy」メソッドが値ではなく参照を返したため、iOne と iTwo の両方の「myProperty」プロパティは 321 に等しくなりました。この動作は予期されたものであり、すべて問題ありません。

ここで、ネイティブ オブジェクト タイプである Number を使用して同じことを試みました。よりオブジェクト指向のプログラマーフレンドリーな方法で、そのインスタンスを作成しましょう:

var iOne = new Number(123);
var iTwo = iOne; //Equals "iTwo = iOne.copy()", except there isn't a copy method

iOne = 321;

そして今、恐ろしいことが起こりました。iOne は 321 ですが、iTwo はその値を維持し、123 のままです。

この動作が何によって引き起こされているのかわかりません。多分 Number はある種の「特別な」ものですか?それに関連付けられた 10 進数は、単なるプロパティ以上のものなのでしょうか? それとも、経験の浅いプログラマーの生活を楽にするためのものなのでしょうか? 最後のオプションは演算子に関連しています。誰かがそれについて何か知っている場合は、JavaScript を理解する私の方法が崩れないようにしてください。

4

4 に答える 4

1

オブジェクト、配列、および文字列は、(コピーではなく) 参照によって割り当てられます。他のすべてのタイプは、割り当てられたときに効果的にコピーされます (たとえば、古い変数とは関係のない新しい変数を作成します)。

文字列は不変であるため、特殊なケースです。文字列を変更すると、常に新しい文字列が作成されるため、以前の割り当てが参照であったとしても、コピーを作成するように動作します。

割り当て:

iOne = 321;

iOne の値を単純なプリミティブ数値型に置き換えているため、他の変数には影響しません。

于 2013-02-17T01:27:27.027 に答える
1
var iOne = new Number(123);
var iTwo = iOne; //Equals "iTwo = iOne.copy()", except there isn't a copy method

iOne = 321;

iOne変数が保持するオブジェクト参照を、個別のプリミティブ番号で上書きしています。

オブジェクトは参照として保持されますが、直接逆参照できるポインターではないため、そのメモリ位置に保持されているデータを置き換えることはできません。変更できるのは (オブジェクトが変更可能な場合)だけです。

具体的には、Numberオブジェクト ラッパーは可変ではないか、少なくともそれが保持するプリミティブ値を置き換えることができません。オブジェクト全体のみを置き換えることができます。

于 2013-02-17T01:28:13.880 に答える
1
iOne = 321;

このコードは321、変数iOneに割り当てて、最初に参照していたものを上書きして、期待どおりに実行しました。

于 2013-02-17T01:28:26.870 に答える
1

「ネイティブ型」と Javascript のオブジェクトの動作に実際の違いはありません (ネイティブ型が不変であることを除いて)。

2番目の例では、変数が指している変数を変更しているだけですがiOne、別の独立iTwo変数が指している変数を変更する必要があるのはなぜですか?

最初のケースでは、代わりに同じオブジェクトを指す2つの変数があり、1つの変数を使用してオブジェクトを変更すると、他の変数を使用して変更を観察できます(明らかに...同じオブジェクトを指しています)。

Javascript では、すべてが常に参照によって行われ、値 (コピー) によって行われることはないと想像できます。何かをコピーしたい場合は、明示的に行う必要があります...配列の場合は、 ;x.slice()の浅いコピーを作成するために使用できます。xオブジェクトの場合、同じことを行うためのプリミティブ関数はないため、コンストラクターを呼び出す必要があります。

一般的な OOP パターンは、コピーを返すメンバー関数を持つ.clone()ことです。これにより、コピーを必要とする人は、すべてのクラスのコピーを作成する方法を知る必要がなくなります。

function P2d(x, y) {
    this.x = x;
    this.y = y;
}

P2d.prototype.clone = function() {
    return new P2d(this.x, this.y);
}

Javascript のプロトタイプ モデルに固有で、場合によっては役立つ可能性がある別の可能性は、元のオブジェクトに影響を与えずに変更できる浅いコピーのように見える別のオブジェクトを作成することですが、読み取り時に元のオブジェクトを参照しています。

function fakeCopy(x) {
    function f() { }
    f.prototype = x;
    return new f;
}

p = new P2d(10, 20);
q = fakeCopy(p);
console.log(q.x); // Displays 10
q.y = 30;
console.log(q.y); // Displays 30
console.log(p.y); // Displays 20 -- original not changed
p.x = 99;
console.log(q.x); // Displays 99 (!)

これは、Javascript オブジェクトに、読み取りのためにメンバーにアクセスするときに検索される「プロトタイプ チェーン」があるために発生します。qはプロトタイプとして空のオブジェクトとして作成されるpため、(読み取り用に) 属性を検索するときに、内部pで何かが見つからない場合は内部を検索しqます。ただし、書き込み時に属性は 内に設定されq、影響はなくp、その時点からq、プロトタイプ チェーンを上る必要はなく、 に存在する値が返されます。

于 2013-02-17T01:36:27.007 に答える