首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 变量作用域与引用机制深度解析

     編輯:PHP 相關知識

变量作用域

PHP 中变量声明位置决定其访问范围(作用域),主要分三类:

1. 局部变量

  • 在函数内部声明。
  • 存储在栈内存,访问速度快。
  • 仅在函数内部有效,函数结束自动销毁。
<?php
function foo() {
    $local = "仅函数内可见";
    echo $local;
}
foo(); // 正常输出
// echo $local; // 报错:未定义变量
?>

2. 全局变量

  • 在函数外部声明,或在函数内用 global $var 声明。
  • 整个脚本生命周期内有效(包含 include/require 的文件)。
  • 底层通过 $GLOBALS['var'] 实现。
<?php
$global = "全局变量";
function bar() {
    global $global; // 建立到 $GLOBALS['global'] 的引用
    echo $global;
}
bar(); // 输出 "全局变量"
?>

3. 静态变量

  • 函数内用 static $var = 初始值 声明。
  • 驻留在静态存储区,函数结束不销毁,下次调用保留上次值。
  • 初始化仅执行一次(首次调用时),后续调用跳过赋值语句。
  • 不能用表达式初始化(如 static $a = strlen("abc") 会报错)。
<?php
function counter() {
    static $count = 0; // 仅首次执行初始化
    $count++;
    echo $count . "\n";
}
counter(); // 1
counter(); // 2
counter(); // 3
?>

类中的静态成员

类属性/方法用 static 修饰,作用域类似,但通过 类名::$prop、self::$prop、parent::$prop 访问,声明在方法外部。

引用机制详解

PHP 引用(&)让不同变量名指向同一内存地址(Zend 核心实现“写时复制” Copy-on-Write)。

1. 变量引用

<?php
$a = "ABC";
$b = &$a; // $b 引用 $a
echo $a; // ABC
echo $b; // ABC
$b = "EFG";
echo $a; // EFG (受影响)
echo $b; // EFG
?>

2. 函数按引用传参

函数定义参数加 &,调用时传入变量,函数内修改参数将影响外部变量。

<?php
function add100(&$num) {
    $num += 100;
}
$val = 1;
add100($val);
echo $val; // 101
?>

3. 函数引用返回

函数声明加 &,调用时赋值也要加 &,才能得到变量引用而非值拷贝。

<?php
function &getStatic() {
    static $b = 0;
    $b++;
    return $b;
}
$a = getStatic();   // 1,值拷贝
$a = 5;
$a = getStatic();   // 2,值拷贝
$a = &getStatic();  // 3,引用返回,$a 与静态 $b 绑定
$a = 5;
$a = getStatic();   // 6,$b 被修改为 5 后再 ++ 变 6
?>

规则:$a = &func() 才是引用返回,相当于 $a = &$b;普通 $a = func() 只是值拷贝。

4. 取消引用

<?php
$a = 1;
$b = &$a;
unset($a); // 仅解除 $a 与值的绑定,$b 仍持有值 1
echo $b; // 1
?>

unset 只断开变量名与值的绑定,不销毁值本身(引用计数归零才销毁)。

5. global 引用本质

<?php
global $var; // 等价于
$var = &$GLOBALS['var'];
?>

6. 对象引用

PHP 5+ 对象默认按引用传递(实际是对象句柄的值传递)。对象方法中 $this 始终指向调用该方法的对象实例。

写时复制 优化

<?php
$a = 1;
$b = $a; // 此时 $a 与 $b 指向同一内存(引用计数=2),无拷贝
$a = "dsd"; // 发生写操作,Zend 自动为 $b 复制一份 $a 的旧值,重新申请内存
?>

此机制极大提升性能:仅读不写时共享内存,写入时才分离。

JavaScript 作用域对比(附录)

  • var aa = 'xxx' 在函数外声明 = 全局变量(无论是否带 var)。
  • 函数内 var 声明 = 局部变量;不带 var = 隐式全局变量(严格模式下报错)。

最佳实践建议

  • 减少全局变量,优先使用函数参数、返回值、依赖注入传递数据。
  • 需修改外部变量时显式用 & 引用传参,语义明确。
  • 静态变量适合函数级缓存、计数器、单例模式内部状态。
  • 大数组/对象传参默认写时复制,无需强制引用优化;仅在确需修改原值时加 &。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved