php基础——函数

函数介绍

  • 完成某一功能的程序代码集合,称为函数
  • 把一段常用的功能代码,封装到一起,做成一个函数,可以提高代码的复用性和可维护性
  • get_defined_functions() 返回所有已定义函数的数组

函数定义

  • 函数的参数列表可以是多个,并且数据类型可以是任意类型
  • 函数内定义的变量是局部变量,只能在函数内使用,与函数外同名变量不冲突
  • 函数中要使用全局变量,使用global关键字
function 函数名(形参1,形参2,n){    // 参数可以不写 
    执行语句;
    return;      // 返回值写不写看需求,如不写默认返回null
}

函数运行原理

代码示例

$num1 = 10;
$num2 = 10;
//此处传参相当于 $n1=$num1; $n2=$num2 传值赋值
function getSum($n1, $n2){
    $res = $n1 + $n2;
    return $res;
}

$val = getSum($num1, $num2);
echo $val;

内存示例
在这里插入图片描述

变量作用域

函数中定义的变量是局部的,函数外不生效

代码示例

function test(){
    $a = 100;
    echo $a;
}

test();
echo $a;  // Notice: Undefined variable: a

内存示例
在这里插入图片描述

global使用全局变量

函数中要使用全局变量,使用global关键字

  • global $a 本质上等价于 $a = &$GLOBAL['a']【重要】
  • global $a 表示希望使用全局区的$a
  • 如果没有全局变量$a,则会先创建全局变量 $a=null
  • var_dump($GLOBALS) 查看所有的全局变量

代码示例

$a = 100;
function test(){
	// global $a 表示希望使用全局区的$a
	// 如果没有全局变量$a,则会先创建全局变量 $a=null
	// global $a 本质上等价于 $a = &$GLOBAL['a'] 引用赋值
    global $a;
    $a = 10;
    echo $a;
}
test();     // 10
echo $a;    // 10
function test(){
	// 如果没有全局变量$a,则会先创建全局变量 $a=null
    global $a;
    var_dump($a);
}

test();         // null
var_dump($a);   // null

内存示例
在这里插入图片描述
流程分析

1.主栈$a 指向100
2.test(),调用函数,在栈区新开辟一个新的空间新栈1,入新栈1
3.入栈后执行global $a,即函数内希望使用一个全局变量$a

  • 如果主栈没有$a则会先创建全局变量$a值为null,然后全局和局部(主栈和新栈)的变量名$a指向全局区的null
  • 如果有则在新栈1创建$a变量名指向全局区100

4.$a = 10,即新栈1中$a将全局区的100改为10
5.函数没写返回值,默认返回null,函数结束,出新栈1,新栈1销毁,新栈1中的数据和与新栈1相关的箭头也都没有了
7.echo $a,主栈中的$a仍指向10,输出10

函数中的静态变量

  • 静态变量的特点,只会被初始化一次
  • 静态区数据在函数执行完后,不销毁,即使不再有变量指向(这是一个特例),直到整个进程结束才销毁

代码示例

function test(){
    $b = 10;
    static $a = 0;
    $a++;
    echo $a;
}
test();
test();
test();

内存示例

  • 第一次调用test()$a初始化指向静态区0,$a++,静态数据变为1,调用结束,新栈1销毁,静态区并不销毁
  • 第二次调用test() a 不 再 初 始 化 为 0 , 直 接 找 到 静 态 数 据 1 , ‘ a不再初始化为0,直接找到静态数据1,` a01a++`,静态数据变为2,调用结束,新栈2销毁,静态区并不销毁
  • 第三次调用test() a 不 再 初 始 化 为 0 , 直 接 找 到 静 态 数 据 2 , ‘ a不再初始化为0,直接找到静态数据2,` a02a++`,静态数据变为3,调用结束,新栈2销毁,静态区仍不销毁,直到整个进程结束才销毁

在这里插入图片描述

函数传参

函数默认参数的值

// $b的默认值为20,如果调用时不填写,以默认值为准,如果填写,以最新的为准
function test($a, $b=20){
    echo $a + $b,'<br>';
}
test(10);       // 30
test(10,1);     // 11

传值赋值
函数参数默认通过值传递

// 函数传参默认值传递  $a = $num
function test($a){
    echo ++$a,'<br>';
}
$num = 10;
test($num);     // 10
echo $num;      // 11    

引用赋值
可以在形参前加&修改为引用传递

// 函数传参方式修改为引用传递  $a = &$num
function test(&$a){
    echo ++$a,'<br>';
}
$num = 10;
test($num);     // 11
echo $num;      // 11

内存示例
在这里插入图片描述

函数传参 – 不定长参数

  • func_num_args — 返回传递给函数的参数数量
  • func_get_arg — 返回参数列表的某一项
  • func_get_args — 返回一个包含函数参数列表的数组

代码示例
函数的参数可以是基本数据类型任意

function fun(){
    return 'hello';
}

function test(){
    $res1 = func_num_args();
    $res2 = func_get_arg(1);
    $res3 = func_get_args();
    var_dump($res1,$res2,$res3);
}

test(1,5,'hi',array(1,2),fun());

练习题

// 传入参数个数不确定,求和
function getSum(){
    $arr = func_get_args();
    $sum = 0;
    foreach ($arr as $value){
        $sum += $value;
    }
    return $sum;
}

echo getSum(1,2,5);
echo getSum(1,-2,5,6);

内部函数

  • 函数和类声明是全局有效的,不管是在多深的函数下声明的类或函数
  • 函数调用时才会会执行函数内部代码 (调用时才入栈执行)

函数内部可以定义函数,供函数内部使用

function test(){
    function fun(){
        echo 'hello world';
    }
    // 内部直接调用内部函数
    fun();
}

test(); // 'hello world'

函数调用时才会会执行函数内部代码

function test(){
    function fun(){
        echo 'hello world';
    }
}
test(); // 这里调用之后 fun()才被定义
fun();	// 'hello world'

可变函数

  • PHP 支持可变函数的概念
  • 如果一个变量名后有圆括号,PHP 将寻找与变量的值同名的函数,并且尝试执行它
  • 可变函数可以用来实现包括回调函数,函数表在内的一些用途
function test(){
    echo 'hello world';
}

$a = 'test';
$a();   // 先解析$a, test(),若有则执行,若没有则报错

函数面试题

写一个函数,接受两个参数$a $b和一个函数$fun,要求通过$fun求$a $b的和

// 新浪面试题:写一个函数,接受两个参数$a $b和一个函数$fun,要求通过$fun求$a $b的和

// 方案一:最容易理解
function test($n1,$n2,$n3){
    echo $n3;
}

function getSum($n1,$n2){
    return $n1 + $n2;
}

$a = 1; $b = 2;
test($a, $b, getSum($a, $b));

==============================
// 方案二:使用可变函数知识点
function test($n1,$n2,$n3){
    echo $n3($n1,$n2);
}

function getSum($m1,$m2){
    return $m1 + $m2;
}

$a = 1; $b = 2; $funName = 'getSum';
test($a,$b,$funName);


=============================
// 方案三:方案二的改进使用
function test($n1,$n2,$n3){
    function getSum($n1,$n2){
        return $n1 + $n2;
    }

    return $n3($n1,$n2);
}


$a = 1; $b = 2; $funName = 'getSum';
echo test($a, $b, $funName);

匿名函数

  • 匿名函数,也叫闭包函数,允许临时创建一个没有指定名称的函数
  • 最经常用作回调函数参数的值
  • 闭包函数也可以作为变量的值来使用,最后要加上分号:
  • 匿名函数其实是一个对象数据类型

代码示例

$fun1 = function ($n1, $n2){
    return $n1 + $n2;
};  // 这里是加;的

// 调用匿名函数
echo $fun1(1,3);

var_dump($fun1);    // object

回调函数

调用某个函数A,而这个函数内又会调用你实现的另一个函数B,那么函数B就是所谓的回调函数

function test($n1,$n2,$n3){
    echo $n3($n1,$n2);
}

function getSum($m1,$m2){
    return $m1 + $m2;
}

$a = 1; $b = 2; $funName = 'getSum';
test($a,$b,$funName);

匿名函数用作回调函数参数的值(开发中用的挺多)

function test($n1, $n2, $n3){
    $sum = $n1 + $n2;
    $res = $n3($sum);	// 回调
    return $res;
}

echo test(1, 3, function ($v){return $v*2;});   // 第三个参数为匿名函数

递归函数

  • 递归函数即自调用函数,在函数体内部直接或间接的自己调用自己
  • 函数体中会附加一个条件判断,以判断是否需要执行递归调用,并且在特定的条件下终止函数的递归

代码示例

function abc($n){	// 此处是传值赋值
    if ($n>2){
        abc(--$n);	// $n = $n-1;  abc($n)
    }
    echo $n,'<br>';
}

abc(4);	// 2 2 3

// 思考: 如果是 $n-- 会怎么?   无限递归

内存示例
在这里插入图片描述
递归练习1 :1 ~ n的和

function sum($n){
    if ($n == 1){
        return 1;
    }
    return $n+sum($n-1);
}

echo sum(100);

递归练习2 :斐波那契数列

// 斐波那契数列  1 1 2 3 5 8 13
function test($n){
    if ($n == 1 || $n == 2){
        return 1;
    }else{
        return test($n-1) + test($n-2);
    }
}

$res = test(5);
echo $res;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值