JavaScriptでオブジェクトのディープコピーをどうやってやるのか、これといったものがないようなので作ってCodeReposにおいておきました。

なぜこういうのが必要かというと、

var a = [0,1,2,3];
alert(a);   // 0,1,2,3
var a2 = a;
a2[4] = 4;  // a2を変えると...
alert(a2);  // 0,1,2,3,4 -- aも変わってしまう!

からです。参照でオブジェクトを実装しているものにはJavaScriptでなくてもこうなっていて、それでは不都合なときのため、たいていの言語ではDeep Copyを実装するクラスやモジュールが提供されていますが(例えばPerlではStorable::dclone()、RubyならMarshalloaddumpを使って)、JavaScriptにはこれといったものが見当たらないのです。

現バージョンのはこちら。

/*
 * $Id: clone.js,v 0.1 2007/11/26 14:17:22 dankogai Exp dankogai $
 */

(function(){
    // They are atomic already
    var atomic = [ Boolean, Number, String, Date, RegExp ];
    for (var i = 0, l = atomic.length; i < l; i++){
        atomic[i].prototype.clone = function(){ return this; }
    }
    // now the moment of truth!
    Object.prototype.clone = function(){
        if (this.prototype && this.prototype.clone 
            && this.prototype.clone !== Object.prototype.clone)
            return this.clone();
        var clone = new (this.constructor);
        for (var p in this) {
            clone[p] = typeof this[p] == 'object' ? this[p].clone() : this[p];
        }
        return clone;
    }
    // Array needs some special care
    Array.prototype.clone = function(){
        var clone = [];
        for (var i = 0, l = this.length; i < l; i++) {
            clone[i] = typeof this[i] == 'object' ? this[i].clone() : this[i];
        }
        return clone;
    }

})();

で、以下が実例。

Source:
stdout:
stderr:

オブジェクトの文字列化のため、KawaさんのJKL.Dumperを使わせていただいております。

見てのとおり、一つ嫌な問題があって、prototypeに割り当てているにも関わらず、for (k in object)clone自身が見えてしまうのです。これって何とかならないのかなあ....__proto__プロパティを使う方法だと新しすぎる?

Dan the JavaScripter