本节讲解的内容
- 函数的概念
- 函数的分类
- 函数的变量问题
- 函数的参数讨论
- 内部函数
- 可变函数
- 匿名函数
- 函数的递归调用
前言
在开发中,我们有时候会使用到大量的函数,那什么是函数,作用又是什么?函数的出现可以说初次引出了封装的概念,函数的使用可以使我们的代码不那么冗余,同时函数的定义可以上我们快速的滤清思路。提高代码的复用性,同时有利于模块化编程。
函数的概念
当我们在编程中,有这样一个需求,需要对一个功能进行统一的整合,以便于在别的地方使用这个功能的时候不用在编写一次(减少冗余性),只需要调用特定的代码就能实现。用现成的技术,我们很难实现这种需求,这时就需要使用到函数这个知识。
函数:为完成某一功能的程序指令(语句)的集合,一般一个函数最好只完成一个功能,降低代码的耦合度。
有时候我们把函数称之为方法,它们两个是一个概念。
函数的分类
几乎每种编程语言的函数都分为两种:
- 自定义函数
- 系统函数
自定义函数:
自定义函数就是我们自己根据自己的具体需求自己定义的函数,函数中的功能需要自己去实现。自定义函数的语法规则:
function 方法名(形参列表){ 实现某种功能的代码; return 返回值(可以没有返回值,这个看需求)}
解释:
- function是一个关键字,如果想定义一个函数必须写function
- 方法名是自己定义的,这个名字你可以随意起,但是一般我们应该起有意义的名字,比如说这个函数要实现什么功能的缩写。
- 形参列表,当我们调用函数的时候,有时候需要传递给函数一些参数(也就是变量),在函数中进行操作,这个形参列表就是接受我们调用时传过来的参数,当然可以有多个。
- 在PHP中函数体是需要大括号包裹起来的,里面写我们的代码。
- return就是返回的意思,当我们调用函数后,有时候需要函数向我们返回一个结果,比如函数的功能是计算两个数的和,这时候当函数通过进行加法运算后,我们可以写return返回计算后的结果,当然有没有返回值需要看函数的具体功能是什么,需不需要返回结果。
函数名的命名规则:
函数名和 中的其它标识符命名规则相同。有效的函数名以字母或下划线打头,后面跟字母,数字或下划线。 我们在写函数是一般的命名规范是驼峰式命名法,也就是第二个单词的首字母大写。示例:
系统函数:
系统函数就是也是函数的一种,是系统已经封装好的函数,系统函数有好多,不同的函数有不同的功能,我们可以根据自己的需求选取不同的函数。
在帮助文档中我们可以查询到我们经常使用的数学函数:
- abs — 绝对值
- ceil — 进一法取整
- decbin — 十进制转换为二进制
- dechex — 十进制转换为十六进制
- decoct — 十进制转换为八进制
- max — 找出最大值
- min — 找出最小值
- pow — 指数表达式
- rand — 产生一个随机整数
- round — 对浮点数进行四舍五入
- sqrt — 平方根
向我们有时使用的var_dump()输出类型就是系统函数。
系统函数使用到的时候可以查看帮助文档。
函数的变量问题
全局变量和局部变量
局部变量:
在函数中我们在处理数据中,可能会定义一些变量,这些在函数中定义的变量我们称之为局部变量,局部:顾名思义,就是在函数中使用的变量。
可以看到当尝试在函数外使用函数内的变量的时候,就会报错。
全局变量:
在上面的代码中我们可以看到在函数外,我们定义两个变量,a和 b,这种在函数外定义的变量我们称之为全局变量。那么全局变量能不能再函数内使用呢?
可以看到,在函数内使用函数外的全局变量时,提示错误。
全局变量称为全局,那怎么在函数内使用呢?答案很简单,只需要在函数中用关键字声明一下就行了。
在函数中利用global这个关键字进行声明,便是需要使用全局变量$a,在这里不得不说一下函数的调用在内存中的变化。
函数的调用过程大致图:
我们的代码都是在栈(也就是内存中)中运行的。在栈中通过一行行的执行代码,进行解析,在运行的时候有一个存放我们数据的区域,叫数据区。当定义变量的时候,在数据区就会生成一个数据区,存放自己定义的变量。
当代码执行到调用函数的时候,系统就会在栈中重新开辟一个栈区,并在这个新栈中执行函数(每执行一个函数就会开辟一个新栈),当在函数中创建对象的时候,就会在数据区重新定义一个区域用来存放函数中的变量。这就是在函数外不能使用函数内变量的原因。它们两个是两个不同的区域。
但是当我们声明了global的时候,系统就不会在函数自己的数据区建立一个变量,而是会去函数外部的数据区,尝试寻找用global定义的变量。但是当外部的数据区没有我们用global定义的变量的时候,就会自动的在外部的数据区定义一个变量,使其成为全局变量。
上面的$a在外部没有定义
函数的参数讨论
我们在调用函数的时候经常会去传过去参数,而在函数上我们也定义了参数进行接受。调用函数时传的参数称为实际参数(实参),而函数接受的参数称为形式参数(形参),它两个是没有影响的,定义时名字一样也是可以的,但是一定要对应,不能出现调用时传过去两个参数,接收时一个参数。
函数的参数是允许有默认值的,也就是当我们没有传过去数值时,它使用默认值,但是当我们传过去有值的时候,使用我们传过去的值。
使用默认的:
可以看到它并没有报错,同时$oper使用了默认的值+;
使用传过去的:
参数的值传递和引用传递
在函数的调用中,参数的传递有两种方式:
- 值传递
- 引用传递
值传递
当我们在调用函数,传递参数后在函数中进行修改,而在函数外再次使用,还是修改前的值,可以看代码:
这种传递方式我们为值传递,默认情况下,函数参数通过值传递(因而即使在函数内部改变参数的值,它并不会改变函数外部的值)。如果希望允许函数修改它的参数值,必须通过引用传递参数。
引用参数
有时我们希望我们传进去的值,在没有返回的情况下,直接进行修改,这是就需要用到引用传递。
在上面的代码中只是在函数中添加了一个取地址符&,学过的都知道,在中使用&直接进行地址的传递。这就表示它在函数中的数据,会指向外边的变量。
内部函数
内部函数: 函数内部可以申明函数,供函数内部使用,称为内部函数
,比如某位程序员为防止他人调用,可以使用内部函数。其实内部函数也是可以在函数外边使用的,就像上面的代码, 如果我们没有执行 calcuator, 就去调用内部函数 sum() ,就会报错。但是如果我们执行过 calculator 则,我们也可以使用内部函数了.
当调用过calcuator,可以理解为内存中有函数内的这两个函数,然后接着调用函数内的函数,就不会出错。
可变函数
可变函数: PHP 支持可变函数的概念。这意味着如果一个变量名后有圆括号,PHP 将寻找与变量的值同名的函数,并且尝试执行它。可变函数可以用来实现包括回调函数,函数表在内的一些用途。
看代码可以比较清晰的理解什么是可变函数。
我们在回调函数中会使用到这种方式。
案列:在上面把一个函数的名字当成变量进行传递。
匿名函数
匿名函数: 匿名函数,也叫闭包函数,允许临时创建一个没有指定名称的函数。最经常用作回调函数参数的值。当然,也有其它应用的情况. 简单的理解就是 匿名函数就是没有名字的函数。
回调函数
上面的代码其实也是一个回调函数。匿名函数当作回调函数来调用。
回调函数简单的理解是:你调用了某个函数,而这个函数(A)内又会调用一个由你实现的另一个函数(B),那么这个另一个函数(B)就是所谓的回调函数,所以,一般来说,你只是不直接去调用罢了。
函数的递归调用
递归直白的说就是自己调用自己,比如函数自己调用自己,递归是一种,它的专业说法是:
递归通过把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大的减少了程序的代码量。
我们在这里只是简单的讨论一下,不做过多的深入。
示例:
2){ abc(--$n); //进行自己调用自己。 } echo '$n的值是' . $n . '';}abc(4);.....结果.....2 2 3
看到结果可能一时没有反应过来。但是如果画图就好理解了。
函数的递归需要满足几个条件:
- 基准情形。必须总要有某些基准条件,它无需递归就能解出 - 不断推进。对于那些需要递归的求解的情形,每一次递归调用都必须要使状况朝向一种基准情形推进总结
上面的讲解的基本上是函数的基本应用,想要熟悉的掌握函数的应用,只用多练,多想。同时,不知道有没有发现,本节的函数都是写在一个文件里面的,但是有时我们写的函数是在另外一个文件,这时就不能再另外一个文件直接使用,上面的所有功能都不能使用,作为PHP程序员,你必须要知道,必然有一种方法能解决这种问题,恩,确实能解决,include和require。