PHP变量 之 对象类型变量

在 PHP 和 JavaScript 中(或许还有其余语言),变量内所保存的值分为 基本类型值引用类型值函数

$obj = new stdClass;

若一个变量是一个对象,那么该变量保存的就是一个引用类型的值,即变量中实际保存的是堆内存中对象的地址,而不是对象的实体;若变量为其余类型,则保存的是基本类型值,而不是引用地址。这一点须要特别注意,由于咱们可能会遇到以下几种状况,不清楚原理可能致使出错。code

赋值

$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_2name 也发生的改变,缘由是 obj_1obj_2 指向同一个对象 #1 ,由于在第二行中,咱们将 obj_1 所指向的对象的地址赋给了 obj_2ip

传递参数

咱们来看这段代码:内存

function setName($obj) {
    $obj->name = 'Xavier';
}

$person = new stdClass;
setName($person);
var_dump($person->name); // 输出 string(6) "Xavier"

若变量为一个对象,那么当它做为参数传递给一个函数时,一样,传递的是一个对象地址,而不是拷贝了一个新的对象实体给参数 $obj 。这样,函数内部并无 return 新的东西出来但改变了外部的状态 的这种状况就变得好理解了。string

接下来,请看这段代码:io

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"

最后的输出结果可能会让不少人会疑惑,他们的思惟多是这样的:function

  1. 我将 person 对象的引用地址传递给 obj参数
  2. 在函数内部第一行,根据 obj 的引用地址,我将函数外部对象的 name 属性设置成了 "Xavier"
  3. 在第二行,我将一个新的对象赋给了 obj ,既然 obj 为函数外部对象的引用,那么外部对象也必定变为了这个新的对象
  4. 而后我再给这个新的对象设置新的 name 属性 "zhao" ,嗯,这样外部对象的 name 必定也变成了 "zhao"

若是你想的和上方相同,那可就大错特错了,缘由在于对传递参数的过程的错误理解。变量

首先,咱们应该明白,将一个变量做为参数传递给函数 能够理解为 将那个变量保存的值 复制一份给 函数的参数(参数即函数范围的局部变量) 。当函数执行时,外部变量函数参数(局部变量) 是同时存在于内存中的,而且二者是相互独立的,虽然二者所保存的值是相同的;函数参数(局部变量) 会在函数执行完毕后被销毁。原理

明白了上述原理,那么咱们从新来看那段代码:

  1. 函数的 obj 变量在函数内第一行保存的是函数外部 person 变量所保存的值,也就是外部对象的地址
  2. 但到了第二行,obj 变量所保存的值变成了新建立的对象的地址,obj 的指向发生了改变,而原来的外部对象依旧存在而且只被 person 一个变量引用,因此在第三行的行为并无影响到 person 所指向的那个对象。新建立的对象在函数执行以后被销毁。

因此有代码中注释的输出结果。

相关文章
相关标签/搜索