Nov 27, 2007
JavaScriptにおけるdeep clone
http://blog.livedoor.jp/dankogai/archives/50957890.html
まず、Object.prototypeにメソッドを生やしてしまうとfor inでキーを列挙するときにいちいちhasOwnPropertyを使わないといけなくなるので普通は使いません。影響が大きすぎるので、よっぽど変態的なライブラリじゃないと使わない。他のライブラリと組み合わせるとほぼ確実に問題が起きる。それから、deep_cloneが欲しい場合はJSONを作ってevalすればよい。パフォーマンスを気にする場合とか、浅いコピーが必要な場合はそれなりに工夫する必要があるけど。
で、JSONにするのにFirefoxだとtoSourceというのが使える。unevalというラッパーがあって、これだとnullでも平気。
http://subtech.g.hatena.ne.jp/cho45/20071125/1195964965
つまりFirefoxだったらeval(uneval(obj))でOK。
これはhasOwnPropertyを使う。prototypeチェーンを辿らないで、そのオブジェクト自身のプロパティとして存在している場合のみtrueを返す。
http://blog.livedoor.jp/dankogai/archives/50957994.html
これも同様、Object.prototypeにtoSourceを自前で定義してしまうと影響が大きすぎるので、使えない。
----
突っ込まれそうなところを補足
- 適切にtoSourceが設定されてれば、任意のクラスのオブジェクトでもeval,unevalでcloneを作れる。
- toJSONでtoSourceと同等の出力を期待するのは間違ってる気がするので、クロスブラウザでunevalを実装した方が良いかも。
- okuさんが書いてるけど、元のオブジェクトに影響を与えないで、一部のプロパティのみを書き換えたオブジェクトを作りたい、という要求を満たすにはまさにprototypeを使った継承が使えるので、他の言語と比べてdeep_cloneの必要性自体が薄い、気がする。(元のオブジェクトの変更が反映されちゃうから微妙か)
こんなの。
プリミティブ値を継承した場合に起こる問題を解消してあるのがこれ。
http://nanto.asablo.jp/blog/2006/10/18/566348
まず、Object.prototypeにメソッドを生やしてしまうとfor inでキーを列挙するときにいちいちhasOwnPropertyを使わないといけなくなるので普通は使いません。影響が大きすぎるので、よっぽど変態的なライブラリじゃないと使わない。他のライブラリと組み合わせるとほぼ確実に問題が起きる。それから、deep_cloneが欲しい場合はJSONを作ってevalすればよい。パフォーマンスを気にする場合とか、浅いコピーが必要な場合はそれなりに工夫する必要があるけど。
で、JSONにするのにFirefoxだとtoSourceというのが使える。unevalというラッパーがあって、これだとnullでも平気。
http://subtech.g.hatena.ne.jp/cho45/20071125/1195964965
つまりFirefoxだったらeval(uneval(obj))でOK。
Object.deep_clone = function(obj){
return (typeof uneval == "function") ? eval(uneval(obj)) : eval(Object.toJSON(obj));
}
// Object.toJSONは別途適当に実装。prototype.jsに入ってたりしますね。
見てのとおり、一つ嫌な問題があって、prototypeに割り当てているにも関わらず、for (k in object)でclone自身が見えてしまうのです。これって何とかならないのかなあ....__proto__プロパティを使う方法だと新しすぎる?
これはhasOwnPropertyを使う。prototypeチェーンを辿らないで、そのオブジェクト自身のプロパティとして存在している場合のみtrueを返す。
obj = {keyname: "hoge"};
"toString" in obj // true
"hasOwnProperty" in obj // true
obj.hasOwnProperty("keyname") // true
obj.hasOwnProperty("hasOwnProperty") // falsehttp://blog.livedoor.jp/dankogai/archives/50957994.html
これも同様、Object.prototypeにtoSourceを自前で定義してしまうと影響が大きすぎるので、使えない。
----
突っ込まれそうなところを補足
- 適切にtoSourceが設定されてれば、任意のクラスのオブジェクトでもeval,unevalでcloneを作れる。
- toJSONでtoSourceと同等の出力を期待するのは間違ってる気がするので、クロスブラウザでunevalを実装した方が良いかも。
- okuさんが書いてるけど、元のオブジェクトに影響を与えないで、一部のプロパティのみを書き換えたオブジェクトを作りたい、という要求を満たすにはまさにprototypeを使った継承が使えるので、他の言語と比べてdeep_cloneの必要性自体が薄い、気がする。(元のオブジェクトの変更が反映されちゃうから微妙か)
こんなの。
function clone(obj){
var F = function(){};
F.prototype = obj;
return new F;
}プリミティブ値を継承した場合に起こる問題を解消してあるのがこれ。
http://nanto.asablo.jp/blog/2006/10/18/566348
WriteBacks
deep cloneを僕も考えてみた
404 Blog Not Found:javascript - お伺い - Object.prototype.clone() 最速インターフェース研究会 :: JavaScriptにおけるdeep clone deep cloneをする方法を僕も考えてみました。 目標は Object.prototypeを汚さない prototypeをたどって得られる要素もコピーする 二番目の
Posted by さらさら宇宙忍法帖 at 2007/11/27 (Tue) 13:10:51
javascript - uneval() for the rest of us!
うーん、それもそうなんだけど....
最速インターフェース研究会 :: JavaScriptにおけるdeep cloneまず、Object.prototypeにメソッドを生やしてしまうとfor inでキーを列挙するときにいちいちhasOwnPropertyを使わないといけなくなるので普通は使いません。
で、JSONにする....
Posted by 404 Blog Not Found at 2007/11/27 (Tue) 19:12:27
Posted by アルバイト at 2008/10/21 (Tue) 14:15:24
Posted by seo対策検索エンジン at 2008/10/21 (Tue) 14:40:27
http://la.ma.la/blog/diary_200711270645.trackback
writeback message: Ready to post a comment.

