2012-04-26 4 views
1

私がやろうとしているのは、Javascriptオブジェクトのclone()関数を構築することです。あなたが知っているように、Javascriptでこのためのネイティブ機能がないと痛いことがあります。私はそれを行うには素晴らしい方法がありますが、ユーザビリティは賢明です、それは厄介です。ここまでは関数です:関数内で引数を再割り当てする方法はありますか?呼び出し元のスコープにも影響しますか?

function clone(objectToClone) { 
    var myClone = function() {}; 
    myClone.prototype = objectToClone; 
    return [ 
     new myClone(), 
     new myClone() 
    ]; 
} 

ご覧のとおり、現在私は両方のクローンで配列を返しています。これは、使用状況を見にこのような何かになり:

// usage 
var bar = new foo(); 
bar = clone(bar); // forks bar into two separate copies of bar (awkward) 
// bar[0] is now clone 1 
// bar[1] is now clone 2 

を私がやりたい何を、以下のような何かを行うことができます:

function clone(objectToClone) { 
    var myClone = function() {}; 
    myClone.prototype = objectToClone; 
    objectToClone = new myClone(); // somehow magically? 
    return new myClone(); 
} 

// usage 
var bar = new foo(); 
var baz = clone(bar); // returns a copy, and bar is now one of the copies as well. 
// bar is now clone 1 
// baz is now clone 2 

残念ながら、これは引数を割り当てているため、動作しません。呼び出し元のスコープには影響しません。私は誰かが希望のマナーの機能を使うことを可能にするいくつかのjsトリッキーを思いつくのに役立つかもしれないことを望んでいました。どんなアイデアも大歓迎です。

+0

なぜコピーがクローンを返さないようにしますか?あなたができることは、スコープ( 'window'のような)と1つ以上の変数の名前をあなたの関数に渡して、それをクローンで置き換えることです。 – muffel

+0

あなたが言っていることを描写するのに困っている@muffel。あなたは答えを精緻化できますか? – dqhendricks

+0

この 'clone'の実装について私がどのように感じるか分かりません。たとえば、オブジェクトのクローニングを続けると、任意の長いプロトタイプチェーンが作成されます(たとえばforループの一部としてクローンを作成していた場合など)。これがあなたの望むものなら、なぜ新しいmyCloneを返すのですか? *編集*:ああ、私は、バズはバーの副作用によって変更される可能性があります参照してください。 – ninjagecko

答えて

0

を使用し、あなたが渡す必要がありますプロパティを持つオブジェクトを作成し、それらのプロパティを変更します。それはあなたがオリジナルを変更することができるjavascriptのリファレンスを取得するための最良の方法です。通常の関数の引数として渡されたときに元のものを変更することはできません。 Javascriptにはこれらのタイプの参照はありません。

function clone(holder) { 
    var myClone = function() {}; 
    myClone.prototype = holder.input; 
    holder.input = new myClone(); // somehow magically? 
    return new myClone(); 
} 

// usage 
var holder = {}; 
var holder.input = new foo(); 
var holder.output = clone(holder); // returns a copy, and holder.input is now a copy too 
// holder.input is now clone 1 
// holder.putput is now clone 2 
+0

残念ながらこれはちょうど厄介ですが、最高の答えです。 – dqhendricks

0

オリジナルをそのままにして、クローン関数にコピーを返すことができます。

これはいくつかの理由で不可能または非現実的である場合、それはあなたができる最善である:

var bar = new foo(); 
var clones = clone(bar); 
bar = clones[0]; 
barCopy = clones[1]; 

あなたは信じられないほど洗練eval策略に頼らない限り。

私は本当にほしいと思うのはちょうどreturn new myClone()であり、決してbarを使用しないと思います。実際に元のテンプレートを複製できるようになったので、これは実際にはもう少しエレガントになります(bar_templateなど)。

+0

いいえ、元の 'bar'オブジェクトを変更するとクローンにも影響があります。基本的に' var baz = bar; 'と同じです。実際のクローンではありません。 – dqhendricks

+0

bar_templateは普遍的に適用できません。クローンしたいオブジェクトごとに新しい関数を作成する必要があります。 – dqhendricks

0

あなたは私のコメントを説明したかった、ここにあなたが行く:

function replaceClones(){ 
    for(var i = 0; i < arguments.length; i++){ 
     var varName = arguments[i]; 
     this[varName] = getClone(this[varName]); 
    }  
} 

function getClone(obj){ 
    var Clone = function(){}; 
    Clone.prototype = obj; 
    return new Clone(); 
} 

replaceClones("varA","varB"); 

あなたが別のスコープをしたい場合は、ちょうどあなたの望ましい結果を得るために

replaceClones.call(newScope,"varA","varB"); 
+0

これはあなたが書いたように実際にはうまくいかないようです。 – dqhendricks

関連する問題