摘要:若一個變量是一個對象,那么該變量保存的就是一個引用類型的值,即變量中實際保存的是堆內存中對象的地址,而不是對象的實體若變量為其他類型,則保存的是基本類型值,而不是引用地址。新創建的對象在函數執行之后被銷毀。
在 PHP 和 JavaScript 中(或許還有其他語言),變量內所保存的值分為 基本類型值 和 引用類型值。
$obj = new stdClass;
若一個變量是一個對象,那么該變量保存的就是一個引用類型的值,即變量中實際保存的是堆內存中對象的地址,而不是對象的實體;若變量為其他類型,則保存的是基本類型值,而不是引用地址。這一點需要特別注意,因為我們可能會遇到如下幾種情況,不清楚原理可能導致出錯。
賦值$obj_1 = new stdClass; $obj_2 = $obj_1; $obj_1->name = "Xavier"; var_dump($obj_1->name, $obj_2->name); var_dump($obj_1, $obj_2);
輸出:
string(6) "Xavier" string(6) "Xavier" object(stdClass)#1 (1) { ["name"]=> string(6) "Xavier" } object(stdClass)#1 (1) { ["name"]=> string(6) "Xavier" }
我們發現 obj_2 的 name 也發生的改變,原因是 obj_1 和 obj_2 指向同一個對象 #1 ,因為在第二行中,我們將 obj_1 所指向的對象的地址賦給了 obj_2 。
傳遞參數我們來看這段代碼:
function setName($obj) { $obj->name = "Xavier"; } $person = new stdClass; setName($person); var_dump($person->name); // 輸出 string(6) "Xavier"
若變量為一個對象,那么當它作為參數傳遞給一個函數時,同樣,傳遞的是一個對象地址,而不是拷貝了一個新的對象實體給參數 $obj 。這樣,函數內部并沒有 return 新的東西出來但改變了外部的狀態 的這種情況就變得好理解了。
接下來,請看這段代碼:
function setName($obj) { $obj->name = "Xavier"; $obj = new stdClass; $obj->name = "Zhao"; } $person = new stdClass; setName($person); var_dump($person->name); // 輸出了 string(6) "Xavier" 而不是 string(6) "Zhao"
最后的輸出結果可能會讓很多人會疑惑,他們的思維可能是這樣的:
我將 person 對象的引用地址傳遞給 obj參數
在函數內部第一行,根據 obj 的引用地址,我將函數外部對象的 name 屬性設置成了 "Xavier"
在第二行,我將一個新的對象賦給了 obj ,既然 obj 為函數外部對象的引用,那么外部對象也一定變為了這個新的對象
然后我再給這個新的對象設置新的 name 屬性 "zhao" ,嗯,這樣外部對象的 name 一定也變成了 "zhao"
如果你想的和上方相同,那可就大錯特錯了,原因在于對傳遞參數的過程的錯誤理解。
首先,我們應該明白,將一個變量作為參數傳遞給函數 可以理解為 將那個變量保存的值 復制一份給 函數的參數(參數即函數范圍的局部變量) 。當函數執行時,外部變量 和 函數參數(局部變量) 是同時存在于內存中的,并且兩者是相互獨立的,雖然兩者所保存的值是相同的;函數參數(局部變量) 會在函數執行完畢后被銷毀。
明白了上述原理,那么我們重新來看那段代碼:
函數的 obj 變量在函數內第一行保存的是函數外部 person 變量所保存的值,也就是外部對象的地址
但到了第二行,obj 變量所保存的值變成了新創建的對象的地址,obj 的指向發生了改變,而原來的外部對象依舊存在并且只被 person 一個變量引用,所以在第三行的行為并沒有影響到 person 所指向的那個對象。新創建的對象在函數執行之后被銷毀。
所以有代碼中注釋的輸出結果。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/94512.html
摘要:對于來說,變量有全局變量和局部變量之分那么,他們都是存儲到一個哈希表內了么其實不是的,變量存儲也有作用域的概念。 上次跟大家講了垃圾回收機制后,有些小伙伴對底層原理比較感興趣,私信問我了一些關于變量的相關知識,既然大家對變量比較感興趣,那么這次我們來系統的講一下變量的底層原理 變量結構 首先,我們還是先擺上我們的zval結構體,即php所有變量都會以zval結構體的形式實現 struc...
摘要:小駝峰法大駝峰法匈牙利命名法變量名屬性類型對象描述。是一種弱類型語言,變量在使用之前并不需要聲明類型,且同一變量可以保存多種不同類型的數據。另外,在函數內部創建的靜態變量是無法在函數外部使用的。 變量標識符 標識符即是變量的名稱,PHP 中關于變量的標識符有以下規則: 由任意字母、數字、下劃線組成,但不能以數字開頭 嚴格區分大小寫 為了科學規范標識符,主要有以下幾種流行的命名方式:...
摘要:若一個變量是一個對象,那么該變量保存的就是一個引用類型的值,即變量中實際保存的是堆內存中對象的地址,而不是對象的實體若變量為其他類型,則保存的是基本類型值,而不是引用地址。新創建的對象在函數執行之后被銷毀。 在 PHP 和 JavaScript 中(或許還有其他語言),變量內所保存的值分為 基本類型值 和 引用類型值。 $obj = new stdClass; 若一個變量是一個對象,那...
摘要:面試專欄正式起更,每周一三五更新,提供最好最優質的面試內容。繼上一篇面試常考內容之面向對象發表后,今天更新面向對象的最后一篇。面向對象的主要特征為封裝繼承多態。為了提高內聚性減少引起變化,單一原則是低耦合高內聚的面向原則上的引申。 PHP面試專欄正式起更,每周一、三、五更新,提供最好最優質的PHP面試內容。繼上一篇PHP面試常考內容之面向對象(2)發表后,今天更新面向對象的最后一篇(3...
摘要:本文適合閱讀用戶有其他語言基礎的童鞋看完語法教程來回顧一下的童鞋傳送門,想全面看一下語法推薦這里毫無基礎然而天資聰慧頗有慧根不要左顧右看說的就是你,老夫這里有一本從入門到放棄,觀你根骨清奇兩銀子賣給你如何看完本文后你會收獲到什么的變量的定義 本文適合閱讀用戶 有其他語言基礎的童鞋 看完w3cschool語法教程來回顧一下的童鞋(傳送門,想全面看一下php語法推薦這里) 毫無基礎然而天...
閱讀 2949·2021-11-23 09:51
閱讀 1666·2021-10-15 09:39
閱讀 1056·2021-08-03 14:03
閱讀 2880·2019-08-30 15:53
閱讀 3437·2019-08-30 15:52
閱讀 2487·2019-08-29 16:17
閱讀 2788·2019-08-29 16:12
閱讀 1647·2019-08-29 15:26