4

別の配列またはオブジェクトから新しい配列またはオブジェクトを作成する最良の方法は何でしょうか。やってから

 var oldvar = {x:1,y:2} //or [x,y]
 var newvar = oldvar

それらをリンクしますが、新しい変数を複製または対処する最善の方法は何でしょうか?

4

2 に答える 2

10

JavaScript の数値

JavaScript の数値は、仕様でプリミティブ値型」と呼ばれるものです

Numbers に関する仕様から:

数値 # Ⓣ<br> 倍精度 64 ビット バイナリ形式の IEEE 754 値に対応するプリミティブ値。

注 Number 値は Number 型のメンバーであり、数値を直接表現したものです。

したがって、あなたの場合、参照ではなく oldvarのコピーnewvarになります。

JavaScript ではNumber、 、BooleanundefinednullまたはStringは値の型です。これら5つのいずれかを渡す場合、実際には参照ではなく値を渡しているため、それらを複製する必要はありません。

(オブジェクト) 以外のものを渡す場合、それらは参照型であるため、クローンを使用する必要があります。

JavaScript でオブジェクトを複製する場合、2 つの方法があります。

浅いクローニング

これは、1 レベルの深さでクローンを作成することを意味します。オブジェクト内のすべてのプロパティが列挙可能であると仮定すると (これは通常、プロパティ記述子を使用していない場合に当てはまります)、次のようなものを使用できます。

var a = {a:3,b:5}; 
var copy = {};
for(var prop in a){ 
 copy[prop] = a[prop];
}

しかし、多くの場合、オブジェクトがプロトタイプから継承するすべてのプロパティではなく、オブジェクト自体のプロパティをコピーしたいので、次のことができます。

var copy = {};
for(var prop in a){
  if(a.hasOwnProperty(prop)){//check that the cloned property belongs to _a_ itself
     copy[prop] = a[prop];
  }
}

これら 2 つのシャロー コピー プロパティは off のみでaあることに注意してください。これらはプロトタイプの設定を処理せず、参照によってすべてのプロパティを複製します (プリミティブ値型自体であるプロパティを除く:))。

ディープコピー

ディープ コピーとは、複数レベルの深さのオブジェクトのクローンを作成することを意味します。ディープコピーはそのように定義されているため(疑似コードで)、これは再帰を呼び出します

CopyObject(object)
    If object is a primitive value type
       return object
    clone := Empty Object
    For every member of object 
        Add CopyObject(member) as a property to clone 
    Return clone

クローンのオブジェクト プロパティにアルゴリズムを再帰的に適用しています。

これは、私があなたのために文書化したサンプル実装です。ES5 (Chrome) を想定していますが、他のブラウザーや古いブラウザーにも簡単に適応させることができます。治療DateRegex特別なケースのような、より多くのことを行います。また、オブジェクト内の循環参照を処理できるように、処理済みのプロパティの辞書も保持します。これは学習用であり、本番用ではありません :) ご不明な点がございましたら、お気軽にお問い合わせください。

var clone = function (a) {
    var passedRefs = [];     // Keep track of references you passed to avoid cycles
    var passedRefCreated = [];
    function clone2(a1) { // Inner function to handle the actual cloning
        var obj;
        if (typeof a1 !== "object" || a1 === null) { // Handle value type
            return a1;
        }
        var locInpPassed = passedRefs.indexOf(a1); // Detect circular reference
        if (locInpPassed !== -1) {
            return passedRefCreated[locInpPassed];
        }
        passedRefs.push(a1); // Add the object to the references to avoid circular references later
        if (a1 instanceof Date) { // Handle date and RegExp for special cases
            obj = new Date(a1.getTime());
        } else if (a1 instanceof RegExp) {
            obj = new RegExp(a1);
        }else if (Array.isArray(a1)){// handle arrays in order for Array.isArray to work. Thanks FizzyTea for catching this.
            obj = [];
        } else { // Create a new object with the prototype of the one we're cloning to support prototypical inheritance. Prototypes are _shared_
            obj = Object.create(Object.getPrototypeOf(a1));
        }
        passedRefCreated[passedRefs.indexOf(a1)] = obj; // Add to the references created dict
        Object.getOwnPropertyNames(a1).forEach(function (prop) { // Go through all the property, even the ones that are not enumerable
            obj[prop] = clone2(a1[prop]); // Call the algorithm recursively, just like in the pseudo code above
        });
        return obj;
    }
    return clone2(a); // Call the inner function that has access to the dictionary 
}

(たとえば、for... inループを使用してプロパティを反復処理できます)。

于 2013-05-04T12:36:27.230 に答える