JavaScriptでディープコピーが必要になった際にPHPでのディープコピーが面倒だったことを思い出してのメモ(JavaScriptも一応メモ)
PHP
class SubObject
{
static $instances = 0;
public $instance;
public function __construct() {
$this->instance = ++self::$instances;
}
public function __clone() {
$this->instance = ++self::$instances;
}
}
class MyCloneable
{
public $object1;
public $object2;
function __clone()
{
// this->object のコピーを作成します。こうしないと、
// 同じオブジェクトを指すことになってしまいます。
$this->object1 = clone $this->object1;
}
}
$obj = new MyCloneable();
$obj->object1 = new SubObject();
$obj->object2 = new SubObject();
$obj2 = clone $obj;
print("元のオブジェクト\n");
print_r($obj);
print("クローンオブジェクト\n");
print_r($obj2);
PHPでオブジェクトをディープコピーをしようとすると
clone
ではオブジェクト内の参照型のものはシャローコピーになるので
参照型のものについては公式のコードの上記のように__clone
を実装してcloneを使えば良いのですが、例えばそのオブジェクトの中に更に参照型があったりした場合もそれぞれに__clone
を実装して行かないといけないので面倒なのでした。
マニュアル通りに対応した後に見つけたのですが以下の方法が何も手を加えなくて良いので便利です。
$new_object = unserialize(serialize($object));
unserialize
を使う際は以下に注意。
ユーザーからの入力をそのままunserialize()に渡してはいけません。
PHPのunserialize関数に外部由来の値を処理させると脆弱性の原因になる
JavaScript
- jQueryを使う
var object = {省略};
var newObject = {};
$.extend(true, newObject, object);
// ObjectとArrayにのみ対応
- lodash.jsを使う
var object = {省略};
var newObject = _.clone(object, true);
var object = {省略};
var newObject = _.cloneDeep(object);
- JSONでのシリアライズは完全ではないようです
参考
http://qiita.com/seihmd/items/74fa9792d05278a2e898
http://qiita.com/knhr__/items/d7de463bf9013d5d3dc0