#函數的概念
函數的分類
函數的變數問題
函數的參數討論
內部函數
可變函數
#「
函數的遞迴呼叫
#前言
在PHP開發中,我們有時候會使用到大量的函數,那什麼是函數,作用又是什麼?函數的出現可以說初次引出了封裝的概念,函數的使用可以使我們的程式碼不那麼冗餘,同時函數的定義可以上我們快速的濾清思路。提高程式碼的複用性,同時有利於模組化程式設計。
函數:為完成某一功能的程式指令(語句)的集合,
一般一個函數最好只完成一個功能,降低程式碼的耦合度。有時候我們把函數稱之為方法,它們兩個是一個概念。
函數的分類
幾乎每個程式語言的函數都分為兩種:自訂函數的語法規則:
function 方法名(形参列表){ 实现某种功能的代码; return 返回值(可以没有返回值,这个看需求) }
方法名稱是自己定義的,這個名字你可以隨意起,但是一般我們應該起有意義的名字,比如說這個函數要實現什麼功能的縮寫。
形參列表,當我們呼叫函數的時候,有時候需要傳遞給函數一些參數(也就是變數),在函數中進行操作,這個形參列表就是接受我們呼叫時傳過來的參數,當然可以有多個。
在PHP中函數體是需要大括號包起來的,裡面寫我們的程式碼。
return就是回傳的意思,當我們呼叫函數後,有時候需要函數向我們傳回一個結果,例如函數的功能是計算兩個數的和,這時候當函數透過進行加法運算後,我們可以寫return回傳計算後的結果,當然有沒有回傳值要看函數的具體功能是什麼,需不需要回傳結果。
函數名稱的命名規則:
函數名稱和 PHP 中的其它標識符命名規則相同。有效的函數名稱以字母或底線打頭,後面跟著字母,數字或底線。範例:
<?php $a = 12; $b = 6; function sum($num1,$num2){//这两个参数就是接受我们调用时传过来的参数 $res = $num1 + $num2; return $res; //计算完两个数的和,返回给调用者。 } $sum = sum($a,$b); //调用函数,在这里我们会传过去两个参数,同时返回结果用$sum接收。 echo $sum;
系統函數就是也是函數的一種,是系統已經封裝好的函數,系統函數有很多,不同的函數有不同的功能,我們可以依照自己的需求選取不同的函數。
sqrt — 平方根
向我們有時使用的var_dump()輸出型別就是系統函數。
系統函數使用到的時候可以查看說明文件。
函數的變數問題
全域變數與局部變數## 局部變數:
在函數中我們在處理資料中,可能會定義一些變量,這些在函數中定義的變數我們稱之為局部變量,局部:顧名思義,就是在函數中使用的變數。<?php $a = 12; $b = 6; function sum($num1,$num2){ $res = $num1 + $num2; //定义了一个变量用来存储两个数的和。 return $res; } $sum = sum($a,$b); echo $res; //尝试在函数外进行输出。 echo $sum; .....结果..... Notice: Undefined variable: res in D:\mywamp\Apache24\htdocs\zendstudio\yunsuanfu\yusuanfu.php on line 14 18
<?php $a = 12; $b = 6; function sum($num1,$num2){ $res = $num1 + $num2; echo $a;//在函数内输出函数外的变量。 return $res; } $sum = sum($a,$b); echo $sum; .....结果..... Notice: Undefined variable: a in D:\mywamp\Apache24\htdocs\zendstudio\yunsuanfu\yusuanfu.php on line 10###可以看到,當函數內使用函數外的全域變數時,提示錯誤。 ###
全局变量称为全局,那怎么在函数内使用呢?答案很简单,只需要在函数中用关键字声明一下就行了。
<?php $a = 12; $b = 6; function sum($num1,$num2){ $res = $num1 + $num2; global $a;//在函数内输出函数外的变量。 echo $a; return $res; } $sum = sum($a,$b); .....结果..... 12
在函数中利用global这个关键字进行声明,便是需要使用全局变量$a,在这里不得不说一下函数的调用在内存中的变化。
函数的调用过程大致图:
我们的代码都是在栈(也就是内存中)中运行的。在栈中通过一行行的执行代码,进行解析,在运行的时候有一个存放我们数据的区域,叫数据区。当定义变量的时候,在数据区就会生成一个数据区,存放自己定义的变量。
当代码执行到调用函数的时候,系统就会在栈中重新开辟一个栈区,并在这个新栈中执行函数(每执行一个函数就会开辟一个新栈),当在函数中创建对象的时候,就会在数据区重新定义一个区域用来存放函数中的变量。这就是在函数外不能使用函数内变量的原因。它们两个是两个不同的区域。
但是当我们声明了global的时候,系统就不会在函数自己的数据区建立一个变量,而是会去函数外部的数据区,尝试寻找用global定义的变量。但是当外部的数据区没有我们用global定义的变量的时候,就会自动的在外部的数据区定义一个变量,使其成为全局变量。
<?php $b = 6; function sum($num1){ global $a;//在函数内通过global定义一个外部没有的变量。 $a = 23; //在函数内进行赋值。 } $sum = sum($b); echo $a; //直接使用函数内的变量。 .....结果..... 23
上面的$a在外部没有定义
我们在调用函数的时候经常会去传过去参数,而在函数上我们也定义了参数进行接受。调用函数时传的参数称为实际参数(实参),而函数接受的参数称为形式参数(形参),它两个是没有影响的,定义时名字一样也是可以的,但是一定要对应,不能出现调用时传过去两个参数,接收时一个参数。
函数的参数是允许有默认值的,也就是当我们没有传过去数值时,它使用默认值,但是当我们传过去有值的时候,使用我们传过去的值。
使用默认的:
<?php $a = 3; $b = 6; function sum($a,$b,$oper = '+'){ //形参和实参名字可以使一样的。 if($oper == '+'){ echo $a + $b; //使用默认的加 }else if($oper == '-'){ echo $a - $b; } } $sum = sum($a,$b); //只传进去两个参数,运算符使用默认的情况。 .....结果..... 9
可以看到它并没有报错,同时$oper使用了默认的值+;
使用传过去的:
<?php $a = 3; $b = 6; function sum($a,$b,$oper = '+'){ //形参和实参名字可以使一样的。 if($oper == '+'){ echo $a + $b; }else if($oper == '-'){ echo $a - $b;//使用传过来的加 } } $sum = sum($a,$b,'-'); //传过去三个参数。
在函数的调用中,参数的传递有两种方式:
值传递
引用传递
值传递
当我们在调用函数,传递参数后在函数中进行修改,而在函数外再次使用,还是修改前的值,可以看代码:
<?php $a = 12; function setA($a){ $a = $a * 12; //把$a的值乘以12; } setA($a);//调用函数 echo $a; .....结果..... 12
这种传递方式我们为值传递,默认情况下,函数参数通过值传递(因而即使在函数内部改变参数的值,它并不会改变函数外部的值)。如果希望允许函数修改它的参数值,必须通过引用传递参数。
引用参数
有时我们希望我们传进去的值,在没有返回的情况下,直接进行修改,这是就需要用到引用传递。
<?php $a = 12; function setA(&$a){ //只是在前面加了一个取地址符号。 $a = $a * 12; //把$a的值乘以12; //函数没有返回值 } setA($a);//调用函数 echo $a; .....结果..... 144
在上面的代码中只是在函数中添加了一个取地址符&,学过C语言的都知道,在C语言中使用&直接进行地址的传递。这就表示它在函数中的数据,会指向外边的变量。
内部函数: 函数内部可以申明函数,供函数内部使用,称为内部函数
,比如某位程序员为防止他人调用,可以使用内部函数。
<?php $a = 12; $b = 6; function calculator($a,$b){ function sum($a,$b){ //在函数内部定义一个函数, return $a + $b; } function subtract($a,$b){ return $a - $b; } return sum($a,$b); // 调用自己定义的函数,把传进来的两个值直接传过去。 } echo calculator($a,$b); //调用函数,对返回结果直接进行输出。 .....结果..... 18
其实内部函数也是可以在函数外边使用的,就像上面的代码, 如果我们没有执行 calcuator, 就去调用内部函数 sum() ,就会报错。但是如果我们执行过 calculator 则,我们也可以使用内部函数了.
<?php $a = 12; $b = 6; function calculator($a,$b){ function sum($a,$b){ //在函数内部定义一个函数, return $a + $b; } function subtract($a,$b){ return $a - $b; } } calculator($a,$b); //调用函数 echo sum($a,$b); //当上面的调用过之后才能这样调用,不然会出错。 .....结果..... 18
当调用过calcuator,可以理解为内存中有函数内的这两个函数,然后接着调用函数内的函数,就不会出错。
可变函数: PHP 支持可变函数的概念。这意味着如果一个变量名后有圆括号,PHP 将寻找与变量的值同名的函数,并且尝试执行它。可变函数可以用来实现包括回调函数,函数表在内的一些用途。
看代码可以比较清晰的理解什么是可变函数。
<?php $a = 12; $b = 6; function add($a,$b){ $res = $a + $b; echo $res; } $fun_name = 'add';//定义一个变量,这个变量的名字是函数的函数名。 $fun_name($a,$b); //把变量当成一个函数名 .....结果..... 18
我们在回调函数中会使用到这种方式。
案列:
<?php $a = 6; $b = 6; function getVal($a,$b,$fun_name){ //第三个参数是一个函数的名字。 return $fun_name($a,$b); //如果一个变量名后有圆括号,寻找与变量的值同名的函数,并且尝试执行它。 } function sum($a,$b){ //在getVal中实际上调用的就是这个函数。 return $a + $b; } echo getVal($a,$b,'sum'); .....结果..... 12
在上面把一个函数的名字当成变量进行传递。
匿名函数: 匿名函数,也叫闭包函数,允许临时创建一个没有指定名称的函数。最经常用作回调函数参数的值。当然,也有其它应用的情况. 简单的理解就是 匿名函数就是没有名字的函数。
<?php $a = 6; $b = 16; function getVal($a,$b,$fun_name){ return $fun_name($a,$b); } echo getVal($a,$b,function($a,$b){ //在传递的时候临时的定义一个匿名函数,没有名字,只有关键字function。 return $a + $b; }); .....结果..... 22
上面的代码其实也是一个回调函数。匿名函数当作回调函数来调用。
回调函数简单的理解是:你调用了某个函数,而这个函数(A)内又会调用一个由你实现的另一个函数(B),那么这个另一个函数(B)就是所谓的回调函数,所以,一般来说,你只是不直接去调用罢了。
递归直白的说就是自己调用自己,比如函数自己调用自己,递归是一种算法,它的专业说法是:
递归通过把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大的减少了程序的代码量。
我们在这里只是简单的讨论一下,不做过多的深入。
示例:
<?php function abc($n){ if($n > 2){ abc(--$n); //进行自己调用自己。 } echo '$n的值是' . $n . '<br>'; } abc(4); .....结果..... 2 2 3
看到结果可能一时没有反应过来。但是如果画图就好理解了。
函数的递归需要满足几个条件:
- 基准情形。必须总要有某些基准条件,它无需递归就能解出
- 不断推进。对于那些需要递归的求解的情形,每一次递归调用都必须要使状况朝向一种基准情形推进
上面的讲解的基本上是函数的基本应用,想要熟悉的掌握函数的应用,只用多练,多想。同时,不知道有没有发现,本节的函数都是写在一个文件里面的,但是有时我们写的函数是在另外一个文件,这时就不能再另外一个文件直接使用,上面的所有功能都不能使用,作为PHP程序员,你必须要知道,必然有一种方法能解决这种问题,恩,确实能解决,include和require。
以上就是PHP基础教程五之函数的内容,更多相关内容请关注PHP中文网(www.php.cn)!