php闭包函数传参问题?

闭包匿名函数,两种传参方式有什么区别呢?

function (int $timer_id) use($sms,$order){
    //...code
});

function () use($time_id,$sms,$order){
    //...code
});

这两种写法有啥区别呢?好像没什么区别。

阅读 2.6k
3 个回答

前者传一个参数,用两个闭包里的变量。后者不接受传参,变量均来自闭包。

如果你的闭包只是在原地调用的话,两种写法确实没什么区别,但是你在写一些框架类的逻辑的时候,你可能会让其他开发者将他们的业务逻辑以闭包的方式传给你,你处理完了一些公共逻辑之后再调用,那两种写法就不一样了:

<?php

// 开发者(使用你框架的人)的业务逻辑
function foo()
{
    $name_foo = "Foo"; // 开发者业务逻辑所需

    $my_func = function ($name) use ($name_foo) {
        echo "Arg \$name is: " . $name . ", \$name_foo is: " . $name_foo . PHP_EOL;
    };

    bar($my_func);
}

// 你的框架提供给开发者的接口,参数是开发者的业务逻辑闭包
function bar(Callable $callback)
{
    $name_bar = "Bar"; // 框架的运行时提供给开发者的参数

    call_user_func($callback, $name_bar);
}

foo();

这种情况下,闭包就不能够写成 function ($name, $name_foo) 了,因为你框架中的 bar() 是没法预知使用方的业务逻辑的,你只能将 公共通用 数据以参数的形式传入

首先要指出一点的是,use($sms,$order) 这里的 use 里面的变量并不是“参数”。

use 的作用是将当前上下文里面的变量显式的「捕获」到闭包里面去,并不是作为参数传递,因为大部分语言都是「隐式」的捕获,所以你不太会发现这的用法。

简单地说,如果写在参数里面,那么在调用的时候,是一定要传递的,而 use 则是捕获的上下文的。

需要注意的是,默认情况下,使用 use 直接捕获的变量,在闭包内对变量的直接修改(重新赋值)是不会影响外部变量的,但是如果是对对象的属性一类的操作,是会影响到的,这与其他大部分语言都不尽相同,如果你需要,则可以添加 & ,进行引用捕获。

就像下面这 JavaScript 代码,他是自动捕获的 name ,而当在闭包内修改 name 时,也会影响到外部的

function foo () {
  var name = 'jack'

  var bar = function () {
    name = 'nie'
  }

  bar()
  console.log(name)
}

foo()

而在 PHP 中则不会,除非你手动在捕获的变量前面加上 & 符号。

<?php

$a = 100;

$foo = function () use ($a) {
    $a = 20;
};
$foo();
var_dump($a); // 100

$bar = function () use (&$a) {
    $a = 0;
};
$bar();
var_dump($a);// 0
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏