1.注意魔术常量被引入的问题
a.php中载入b.php【其中b.php中输出魔术常量__FILE__输出的是b.php的路径】
魔术常量被编译的顺序要在a中代码进行处理之前【可以理解为魔术常量在引入前的编译过程中就已经被预编译】
魔术常量相当于占位符【而不是一个引入文件中的变量】
【注意魔术常量的处理方式】
对文件载入过程的理解进一步【就是文件载入语句在文件中执行时,对被载入文件进行编译和复制(这样保证载入的问题的解决)】
【另外载入文件的作用域问题:载入文件的作用域取决于被载入的位置(例子就是在function中载入某文件,则该文件中变量作用域就处在function中)】
【把魔术常量看做是一个特例即可】
2.call_user_func_array();//实现自定义函数和参数的传递
3.函数的递归调用!!!【重点】
函数体内再调用函数本身!!!
【递归本身并没有难点,function可以再任意情况下被调用,因为function本身就是一组执行代码的组合,可以被随意调用,只是外层function一直没有正常return罢了,也就是说function的层结束需要return关键字来进行描述。】
function f1(){
f1();//这里就实现调用,只不过需要对条件进行判断
}
适合递归调用的场景:例如遍历目录这样的情况
调用的情况处理是一致的,就是有一个结束的条件出现【因为这样递归调用的话,能够节省定义函数的次数】
其实递归调用在实际使用情况是比较少用
【只是针对将一个复杂的事情分解,直到事件无法分解为止】
例子:通过递归实现斐波那契数列【后一项是前两项的和】
function f($n){
//首先对基本条件进行筛选
if ($n ==1 ){
return 1;
}elseif($n==2) {
return 1;
}
//开始使用公式进行递归
return f($n-1) + f($n-2);
}
f();//初始化调用
以上便实现了递归
递归的重点:
(1)递归点:什么时候发生递归
(2)递归的出口:什么时候递归结束
其实递归本身并没有任何难度,和直接调用function没有区别,就是调用需要使用的条件进行判断需要注意
【函数的调用本身也不需要太过多虑,就是简单的声明和调用的问题,正常理解即可】
4.迭代
通过迭代进行斐波那契数列的实现
function f($n){
$before_1=1;
$before_2=1;//初始化$n前两项值
//还需要对$n前两项的条件判断
//对前两项进行切换,一直迭代循环,便能一直得到
for($i=3;$i<=$n;$n++){
//迭代掉前两项的值,然后相加即可
}
}
通过迭代处理递归的要素能够很好的回避递归使用场景。
迭代的语法体系就是循环结构【这一点要注意:通过循环来实现递归这样的循环执行的效果】
【所以根本不冲突】
【而且使用迭代的话,效率更好】
迭代和递归都属于分治算法【将一个复杂的问题分开几个小问题,然后再处理】
5.处理函数的函数
function handling【手册中使用】
一些比较常见的处理函数使用
function_exists()【返回一个布尔值】
create_function()【返回一个函数名】【通过这个方法对已有的方法进行重组】
魔术常量__FUNCTION__【在函数内获得当前函数名(例如递归调用中动态调用自身)】
到目前为止创建函数的方法
function+函数名
function+匿名函数
creat_function创建一个比较灵活的函数
6.匿名函数
实现途径是通过closure对象来实现
USE语法【注意】
<?php
$name = 'PHP';
$sayHi = function()use($name){
echo "hi,$name"; //使用use语法之后,$name就会被使用查找外部一层的变量
};
$sayHi();
?>
只有针对匿名函数时能够这样使用use语法么【面向对象中也有,但是现如今在匿名情况下才会使用】
【匿名函数中也可以使用$GLOBALS的使用也可以】
注意use使用的值也分为引用传递和值传递【就是对传递的值改变之后对原值是否影响】
【注意:这个是一个重点】
function outer(){
for($i=1;$i<=3;++$i){
$GLOBALS['f'.$i] = function ()use(& $i){
//这里的$GLOBALS实现闭包的效果
//注意这里的匿名函数对$i的修改
return $i;
};
}
}
outer();//调用该函数
echo $f1();//4
echo $f2();//4
echo $f3();//4
以上的执行顺序其实是这样的:
在函数声明阶段就将三个$f1/$f2/$f3这三个函数都已经完成定义【牢记这一点是关键,函数在声明时的作用域就已经实现了,而不是调用的时候才能实现】,他们三个的返回值都是$i【因为$i此时是被传引用,所以在循环中,输出的$i的更改都会被指向同一个地址,所以return $i使结果变成同一个】
另外将匿名函数做临时函数,也是匿名函数的一个场景【其实凡是在代码中的方法需要使用回调函数的情形,都可以使用匿名函数做回调函数】【匿名函数的定义方式将普通函数定义的预编译时间省略掉,只有回调时进行声明,和使用即可】
7.数组
按照键值对的关系进行分类:关联数组【键名会表示元素的逻辑】和索引数组【数字做键,表示元素的位置】
按照数组的维数分为:一维数组和多维数组【数组中的元素是否是数组】
【php中的多维数组其实更偏向一个递归的概念】
【重点:数组的遍历】
这是数组操作的重点,通过遍历,将数组内的数据实现更好的控制
for和foreach用法来遍历数组
foreach的遍历更为常用和适用场景比较丰富【foreach在执行之时,会进行一次初始化指针的操作。在执行过程中,会移动指针】
【两个重点:数组指针和数组键值对引用关系】
【遍历需要通过数组指针来实现:每个数组中都有一个指针,在某个时刻指向某个元素。在默认情况下指向第一个元素】
【数组中的键值关系就是一个引用关系,所以想要修改数组中的值,需要新加字段,或者修改为按引用传值(在数组遍历阶段有两种途径:1.使用&来实现按引用
2.使用key来重置该引用【这也就是只修改遍历后的临时$value并不会成功的原因】)】
foreach的用法实质是:
首先复制该数组,然后对该数组进行遍历操作并不会影响原数组的操作【遍历操作】
$names=array('123','345');
foreach ($names as $key=>$value) {
var_dump($key,$value);//但是遍历的是原数组的拷贝
echo '<br>';
$names[] = '987';//这里操作的是原数组
}
var_dump($names);//输出的是原数组
【foreach的这种拷贝机制实现的就是一旦自己修改的原数组的操作新加元素之后,会导致了foreach的死循环】
【也就是说foreach内循环体操作的动作并不会影响foreach的循环操作。二者是分离的】
8.指针函数:用来操作指定的情况【其实更多是用来模拟数据结构时使用】
next/current/prev/end/
reset使用非常多,使用之后不能使用相对指针【reset用来重置数组指针】
each()集合了key,current,next三个函数的效果【会返回当前元素的键值信息,并将指针向前移一位】
使用each+while遍历数组【each可以实现key,current,next方法】
$names = array('123','234');
while($element = each($names)){
$key = $element['key'];
$value = $element['value'];
var_dump($key,$value);
}
each()实现了current和next的方法【使用each和while实现了遍历的功能】
采用list+each+while实现优化遍历
利用一个索引数组,同时初始化多个数据【list的用途】
list只能优化$key和$value的赋值语句【对遍历判断没有任何帮助】