先說一下深拷貝和淺拷貝通俗理解
深拷貝:賦值時值完全複製,完全的copy,對其中乙個作出改變,不會影響另乙個
淺拷貝:賦值時,引用賦值,相當於取了乙個別名。對其中乙個修改,會影響另乙個
php中, = 賦值時,普通變數是深拷貝,但對物件來說,是淺拷貝。也就是說,物件的賦值是引用賦值。(物件作為引數傳遞時,也是引用傳遞,無論函式定義時引數前面是否有&符號)
php4中,物件的 = 賦值是實現乙份副本,這樣存在很多問題,在不知不覺中我們可能會拷貝很多份副本。
$obj = new student();
$obj2 = $obj;//將會導致兩個student物件,而不是同乙個student物件的兩次引用,從而導致了許多不明顯的bug(程式設計師無意中修改了某個物件,而希望在其他的引用上看到改變,而實際上在其他引用上完全沒有改變)
幸運的是,php4中存在一種強制按引用傳遞的方式,
//按引用賦值
$obj2 = &$obj;//obj2和obj指向同一物件
//按引用傳遞
function setschool(& $obj)
//按引用返回
function & setschool()
php5中,物件的 = 賦值和傳遞都是引用。要想實現拷貝副本,php提供了clone函式實現。
clone完全copy了乙份副本。但是clone時,我們可能不希望copy源物件的所有內容,那我們可以利用__clone來操作。
在__clone()中,我們可以進行一些操作。注意,這些操作,也就是__clone函式是作用於拷貝的副本物件上的
<?php
//普通物件賦值,深拷貝,完全值複製
$m
= 1;
$n
=
$m
;
$n
= 2;
echo
$m
;
//值複製,對新物件的改變不會對m作出改變,輸出 1.深拷貝
echo
php_eol;
/****************===*/
//物件賦值,淺拷貝,引用賦值
class
test
$m
=
new
test();
$n
=
$m
;
//引用賦值
$m
->a = 2;
//修改m,n也隨之改變
echo
$n
->a;
//輸出2,淺拷貝
echo
php_eol;
?>
由於物件的賦值時引用,要想實現值複製,php提供了clone函式來實現複製物件。
但是clone函式存在這麼乙個問題,轉殖物件時,原物件的普通屬效能值複製,但是源物件的物件屬性賦值時還是引用賦值,淺拷貝。
<?php
class
test
class
testone
}
$m
=
new
testone();
$n
=
$m
;
//這是完全的淺拷貝,無論普通屬性還是物件屬性
$p
=
clone
$m
;
//普通屬性實現了深拷貝,改變普通屬性b,不會對源物件有影響
$p
->b = 2;
echo
$m
->b;
//輸出原來的1
echo
php_eol;
//物件屬性是淺拷貝,改變物件屬性中的a,源物件m中的物件屬性中a也改變
$p
->obj->a = 3;
echo
$m
->obj->a;
//輸出3,隨新物件改變
?>
要想實現物件真正的深拷貝,有下面兩種方法:
寫clone函式:如下
<?php
class
test
class
testone
//方法一:重寫clone函式
public
function
__clone()
}
$m
=
new
testone();
$n
=
clone
$m
;
$n
->b = 2;
echo
$m
->b;
//輸出原來的1
echo
php_eol;
//可以看到,普通屬性實現了深拷貝,改變普通屬性b,不會對源物件有影響
//由於改寫了clone函式,現在物件屬性也實現了真正的深拷貝,對新物件的改變,不會影響源物件
$n
->obj->a = 3;
echo
$m
->obj->a;
//輸出1,不隨新物件改變,還是保持了原來的屬性
?>
第二種方法,利用序列化反序列化實現,這種方法實現物件的深拷貝簡單,不需要修改類
<?php
class
test
class
testone
}
$m
=
new
testone();
//方法二,序列化反序列化實現物件深拷貝
$n
= serialize(
$m
);
$n
= unserialize(
$n
);
$n
->b = 2;
echo
$m
->b;
//輸出原來的1
echo
php_eol;
//可以看到,普通屬性實現了深拷貝,改變普通屬性b,不會對源物件有影響
$n
->obj->a = 3;
echo
$m
->obj->a;
//輸出1,不隨新物件改變,還是保持了原來的屬性,可以看到,序列化和反序列化可以實現物件的深拷貝
?>
還有第三種方法,其實和第二種類似,json_encode之後再json_decode,實現賦值
js 物件深拷貝 深拷貝與淺拷貝
前言 最近在複習一些面試的知識點,剛剛好複習到了這一部分,於是就寫下這篇文章記錄一下。一 值型別和引用型別 在學習深拷貝和淺拷貝之前,我們先來了解一下js的變數型別。值型別 vs 引用型別 值型別 值型別主要有 number,string,boolean,symbol,null,undefined ...
PHP中物件的深拷貝與淺拷貝
先說一下深拷貝和淺拷貝通俗理解 深拷貝 賦值時值完全複製,完全的copy,對其中乙個作出改變,不會影響另乙個 淺拷貝 賦值時,引用賦值,相當於取了乙個別名。對其中乙個修改,會影響另乙個 php中,賦值時,普通物件是深拷貝,但對物件來說,是淺拷貝。也就是說,物件的賦值是引用賦值。物件作為引數傳遞時,也...
物件的淺拷貝與深拷貝
工作中可能會遇到這樣乙個問題,我明明把資料拷貝了乙份,但改變拷貝後的資料居然同時會改變原始資料中的值。那就來看看為什麼吧,希望這篇文章可以給你解惑。只拷貝了資料物件的第一層,深層次的資料值與原始資料會互相影響 拷貝後的資料與原始資料還存有關聯 常見淺拷貝的方式 object.assign 擴充套件運...