在匿名函数出现之前,所有的函数都需要先命名才能使用
1 function increment($value)2 {3 return $value + 1;4 }5 6 array_map('increment', [1, 2, 3]);
有的时候函数可能只需要高中语文成语使用一次,这时候使用匿名函数会使得代码更加简洁直观,同时也避免了函数在其他地方被使用
1 array_map(function($value){2 return $value + 1;3 }, [1, 2, 3]);
php 将闭包和匿名函数视为同等概念(本文统称为匿名函数),本质上都是伪装成函数的对象。
匿名函数的本质是对象,因此跟对象一样可将匿名函数赋值给某一变量
1 $greet = function(string $name){2 echo "hello {$name}";3 }4 5 $greet("jack") // hello jack
所有的匿名函数都是closure
对象的实例
$greet instanceof closure // true
对象并没有什么父作用域可言,所以需要使用u
来手动声明使用的变量,
1 $num = 1;2 $func = function() u($num){3 $num = $num + 1;4 echo $num;5 }6 $func(); // 27 echo $num; // 还第一次学游泳是 1
如果要让匿名函数中的变量生效,需要使用引用传值
1 $num = 1;2 $func = function() u(&$num){3 $num = $num + 1;4 echo $num;5 }6 $func(); // 27 echo $num; // 2
从 php 5.4 开始,在类里面使用匿名函数时,匿名函数的$this
将自动绑定到当前类
1 class foo { 2 public function bar() 3 { 4 return function() { 5 return $this; 6 }; 7 } 8 } 9 10 $foo = new foo();11 $obj = $foo->bar(); // closure()12 $obj(); // foo
如果不想让自动绑定生效,可使用静态匿名函数
1 class foo { 2 public function bar() 3 支点教育 { 4 return static function() { 5 return $this; 6 }; 7 } 8 } 9 $foo = new foo();10 $obj = $foo->bar(); // closure()11 $obj(); // using $this when not in object context
十八岁成人礼
匿名函数的本质是closure
对象,包括了以下五个方法
1 closure {2 private __construct ( void )3 public static bind ( closure $closure , object $newthis [, mixed $newscope = "static" ] ) : closure4 public bindto ( object $newthis [, mixed $newscope = "static" ] ) : closure5 public call ( object $newthis [, mixed $... ] ) : mixed6 public static fromcallable ( callable $callable ) : closure
}
__construct
– 防止匿名函数被实例化
$closure = new \closure();// php error: instantiation of 'closure' is not allowed
closure::bindto
– 复制当前匿名函数对象,绑定指定的$this
对象和类作用域。通俗的说,就是手动将匿名函数与指定对象绑定,利用这点,可以扩展对象的功能。
1 // 定义商品类 2 class good { 3 private $price; 4 5 public function __construct(float $price) 6 { 7 $this->price = $price; 8 } 9 }10 11 // 定义一个匿名函数,计算商品的促销价12 $adddiscount = function(float $discount = 0.8){13 return $this->price * $discount;14 }15 16 $good = new good(100);17 18 // 将匿名函数绑定到 $good 实例,同时指定作用域为 good19 $count = $adddiscount->bindto($good, good::class); 20 $count(); // 8021 22 // 将匿名函数绑定到 $good 实例,但是不指定作用域,将无法访问 $good 的私有属性23 $count = $adddiscount->bindto($good); 24 $count(); // 报错
closure::bind
–bindto
方法的静态版本,有两种用法:
用法一:实现与bindto
方法同样的效果
$count = \closure::bind($adddiscount, $good, good::class);
用法二:将匿名函数与类(而不是对象)绑定,记得要将第二个参数设置为null
1 // 商品库存为 10 2 class good { 3 static $num = 10; 4 } 5 6 // 每次销售后返回当前库存 7 $ll = static function() { 8 return"当前库存为". --static::$num ; 9 };10 11 // 将静态匿名函数绑定到 good 类中12 $sold = \closure::bind($ll, null, good::class);13 14 $sold(); // 当前库存为 915 $sold(); // 当前库存为 8
call
– php 7 新增的call
方法可以实现绑定并调用匿名函数,除了语法更加简洁外,性能也更高
1 // call 版本2 $adddiscount->call($good, 0.5); // 绑定并传入参数 0.5,结果为 503 4 // bindto 版本5 $count = $adddiscount->bindto($good, good::class); 6 $count(0.5); // 50
fromcallable
– 将给定的callable
函数转化成匿名函数
1 class good { 2 private $price; 3 4 public function __construct(float $price) 5 { 6 $this->price = $price; 7 } 8 } 9 10 function adddiscount(float $discount = 0.8){11 return $this->price * $discount;12 }13 14 $closure = \closure::fromcallable('adddiscount');15 $good = new good(100);16 $count = $closure->bindto($good); 17 $count = $closure->bindto($good, good::class); // 报错,不能重复绑定作用域18 $count(); // 报错,无法访问私有属性
fromcallable
等价于
1 $reflexion = new reflectionfunction('adddiscount');2 $closure = $reflexion->getclosure();
这里有一点需要特别注意的是,无论是fromcallable
转化成的闭包,还是使用反射得到的闭包,在使用bindto
时,如果第二个参数指定绑定类,会报错
cannot rebind scope of closure created by reflectionfunctionabstract::getclosure()
本文发布于:2023-04-07 21:09:19,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/9c5af0ec07c5764b0b48146e0c04dd74.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:PHP 核心特性 – 匿名函数.doc
本文 PDF 下载地址:PHP 核心特性 – 匿名函数.pdf
留言与评论(共有 0 条评论) |