闭包函数中use使用

2023-05-16

匿名函数中的use,其作用就是从父作用域继承变量。 

下例是最常见的用法,如果不使用use,函数中将找不到变量$msg。

1
2
3
4
5
6
7
8
<?php
$msg = [1,2,3];
$func = function () use ( $msg ){
     print_r( $msg );
}; 
 
$func ();
?>

运行输出

1
2
3
4
5
6
Array
(
     [0] => 1
     [1] => 2
     [2] => 3
)

关于继承变量的时机

继承变量的行为是在函数定义时产生还是在函数调用时产生?我们调整下上例中代码的顺序,将$msg置于函数定义之后。

1
2
3
4
5
6
7
8
9
<?php
$func = function () use ( $msg ){
     print_r( $msg );
}; 
 
$msg = [1,2,3];
 
$func ();
?>

运行输出

1
PHP Notice:  Undefined variable: msg in /search/ballqiu/c.php on line 4

可见,继承变量的行为是在函数定义时产生的。上例中定义

msg,所以函数运行时$msg就是未定义变量。


关于use中使用引用传值

我们知道,在匿名函数的use中如果使用引用传值,那么匿名函数中对参数值的改变会同样影响外部相应变量。比如下面的例子:

1
2
3
4
5
6
7
8
9
10
11
12
<?php
$msg = [1,2,3];
$func = function () use (& $msg ){
     $msg [0]++;
     print_r( $msg );
};
 
 
$func ();
 
print_r( $msg );
?>

运行输出

1
2
3
4
5
6
7
8
9
10
11
12
Array
(
     [0] => 2
     [1] => 2
     [2] => 3
)
Array
(
     [0] => 2
     [1] => 2
     [2] => 3
)

那么是不是任何情况下,想通过匿名函数改变外部变量值都一定要通过引用方式向use传值呢?看下面这个例子:

1
2
3
4
5
6
7
8
9
10
<?php
$msg = new ArrayObject([1,2,3], ArrayObject::ARRAY_AS_PROPS);
$func = function () use ( $msg ){
     $msg [0]++;
     print_r( $msg );
};
 
$func ();
print_r( $msg );
?>

运行输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
ArrayObject Object
(
     [storage:ArrayObject: private ] => Array
         (
             [0] => 2
             [1] => 2
             [2] => 3
         )
 
)
ArrayObject Object
(
     [storage:ArrayObject: private ] => Array
         (
             [0] => 2
             [1] => 2
             [2] => 3
         )
 
)

可见,如果传递object类型的变量,即使不显示使用引用传递,匿名函数中变量值的改变同样会影响到外部相关变量。

但是,问题又来了。向use传递object变量时,使用引用与不使用引用到底有没有区别呢?还是来看例子

1
2
3
4
5
6
7
8
<?php
$func = function () use ( $msg ){
     echo $msg [0], "\n" ;
};
 
$msg = new ArrayObject([1,2,3], ArrayObject::ARRAY_AS_PROPS);
$func ();
?>

我们改为使用引用传递

1
2
3
4
5
$func = function () use (& $msg ){
     echo $msg [0], "\n" ;
};
 
运行输出1

可见使用引用传递时,即使变量滞后于函数定义,函数内部还是可以找到外部相应的变量,不会出现变量未定义的情况。两者还是有区别的。



关于class中匿名函数里的this及use

1
2
3
4
5
6
7
8
9
10
<?phpclass C{
     protected $_num = 0;    public function mkFunc(){
         $func = function (){
             echo $this ->_num++, "\n" ;
         };        return $func ;
     }    public function get(){
         echo $this ->_num, "\n" ;
     }
} $obj = new C(); $func = $obj ->mkFunc(); $func (); $obj ->get();?>
运行结果01

可见匿名函数里的this就是指当前对象,不需要使用use就可以直接找到。

还是上面的例子,如果一定要使用use会是什么效果呢? 
将mkFunc改为

1
2
3
4
5
6
7
8
9
public function mkFunc(){
     //唯一改动是此处加了use
     $func = function () use ( $this ){
         echo $this ->_num++, "\n" ;
     };    return $func ;
}
 
运行输出
PHP Fatal error:  Cannot use $this as lexical variable

修改为

1
2
3
4
5
6
7
public function mkFunc(){
     $self = $this ;    $func = function () use ( $self ){
         echo $this ->_num++, "\n" ;
     };    return $func ;
}
 
运行结果01

可见是否使用use,效果是一样的。



use最常用在给类取别名

use还可以用在闭包函数中,代码如下

[php]  view plain  copy
  1. <?php  
  2. function test() {  
  3.     $a = 'hello';  
  4.     return function ($a)use($a) {  
  5.         echo $a . $a;  
  6.     };  
  7. }  
  8. $b = test();  
  9. $b('world');//结果是hellohello  

当运行test函数,test函数返回闭包函数,闭包函数中的use中的变量为test函数中的$a变量,当运行闭包函数后,输出“hellohello”,由此说明函数体中的变量的优先级是:use中的变量的优先级比闭包函数参数中的优先级要高

use中的参数也可以使用引用传递的,代码如下

[php]  view plain  copy
  1. <?php  
  2. function test() {  
  3.     $a=18;  
  4.     $b="Ly";  
  5.     $fun = function($num$nameuse(&$a, &$b) {  
  6.         $a = $num;  
  7.         $b = $name;  
  8.     };  
  9.     echo "$b:$a<br/>";  
  10.     $fun(30,'wq');  
  11.     echo "$b:$a<br/>";  
  12. }  
  13. test();  
  14. //结果是Ly:18  
  15. //结果是wq:30  
[php]  view plain  copy
  1. <?php   
  2. function index() {  
  3.     $a = 1;  
  4.       
  5.     return function () use(&$a){  
  6.         echo $a;  
  7.         $a++;  
  8.     };   
  9. }  
  10.   
  11. $a = index();  
  12.   
  13.   
  14. $a();  
  15. $a();  
  16. $a();  
  17. $a();  
  18. $a();  
  19. $a();  
  20. //123456  
  21.  ?>  

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

闭包函数中use使用 的相关文章

随机推荐

  • 数据库字段的长度 作用

    数据库字段的长度 指的是字节 作用 xff1a 如果不指定长度 xff0c 数据库在存储的时候都必须给每个字段预留最大的存储空间 xff0c 这样极大的浪费了空间 xff0c 也加大了数据库本身管理的难度 字段类型长度应设置为保证正常使用需
  • 飞控常见问题汇总

    1 mavros不能正常通信 失败原因如下 xff1a 用万用表检查Tx xff0c Rx xff0c GND的线是否断了 xff0c 杜邦线很容易线芯断掉 USB转TTL的小板子是否工作正常 xff0c 使用ls l dev grep t
  • PHP面试篇之基础0

    个人气场 技术实力 职业规划及贡献 1 深入理解PHP到底是什么 跨平台 xff08 window Linux Unix xff09 服务器端脚本语言 和apache配合方便 xff0c 性能很高因为PHP可以编译成apache模块 无须编
  • IT人士必备网站

    搜索网站 www 3bsou com www baigoogledu com 1 xff0c 免费动态域名申请 http www 3322 org 希网 http comexe cn 科迈 http www comexe cn http w
  • Mysql数据库数据类型详解

    MySQL的数据类型非常多 xff0c 选择正确的数据类型对于获得高性能至关重要 三大原则 xff1a 1 xff0c 更小的通常更好 xff0c 应该尽量使用可以正确存储数据的最小数据类型 2 xff0c 简单就好 xff0c 简单数据类
  • 符姓大全

    符蓉珊 符海瑛 符海英 符海瑛 符何瑛 符小菲 符睿智 符语嫣 符天翔 符天翔 符芮嘉 符文 符程 符自然 符李颜 符海瑛 符虹清 符天恩 符斌 符运波 符浩 符立 符若兮 符司晨 符尔岚 符若萱 符诗嘉 符思嘉 符斯嘉 符颖欣 符诗嘉 符
  • 什么是socket

    什么是网络套接字 xff08 Socket xff09 xff1f Socket是网络上两个程序双向通讯连接的端点 对于一个Socket而言 xff0c 它至少需要3个参数来指定 xff1a 1 xff09 通信的目的地址 xff1b 2
  • Samba服务安装

    Samba服务 xff08 共享文件 xff09 一 xff0c 安装1 apt get install samba2 apt get install samba common3 xff09 apt get install cifs uti
  • Ubuntu14配置nginx虚拟主机

    一 建立项目目录 在 home share 目录下创建一个test项目目录 xff0c 并编辑一个子目录 index php 文件 sudo mkdir p home share test 新建一个主页 index php文件 sudo v
  • 记忆方法

    数字编码联系法 xff1a 就是把数字 翻译 成编程 xff0c 然后用联想的方式把这些编程串连起来 xff0c 这就叫数字编码联系法 这种方法适用于临时记忆一些多位数字或数量不太大 xff0c 又不需长期保持记忆的数字 另外 xff0c
  • PHP 使用 file_get_contents 接收 POST 的資料

    一般接收 POST 资料都是使用 POST 这个变量 xff0c 但 POST 只能取得 Content type 為 application x www form urlencoded 或 multipart form data 的資料
  • 浮点数转成整型intval

    n 61 34 19 99 34 var dump intval n 100 int 1998 var dump strval n 100 string 4 34 1999 34 var dump intval strval n 100 i
  • 《硬件合集》Nvidia NX & Pixracer接线图 &电调调参 BLheliSuite

    Nvidia NX 1 针脚定义 2 电源接口关系图 3 使用技巧 值得一提的是 NX的针脚中ttyTHS0可以用作mavros的通信端口 xff0c 正好的Tx Rx串口通信 只需要交叉接线即可 xff0c 并每次运行时为该端口赋予sud
  • self :: 和 this-> 的用法

    在访问PHP类中的成员变量或方法时 xff0c 如果被引用的变量或者方法被声明成const xff08 定义常量 xff09 或者static xff08 声明静态 xff09 那么就必须使用操作符 反之如果被引用的变量或者方法没有被声明成
  • 程序是怎样运行的

    一 CPU的内部结构解析 1 程序运行流程 程序员用C语言等高级语言编写程序 int a a 61 1 43 2 printf 34 d 34 a 将程序编译后转换成机器语言的EXE文件 01000101000010111 00110100
  • 人性的弱点 --卡耐基

    自序 成就此书的因缘 和人类所具备的潜能相比 xff0c 我们仍处于蒙昧之中 人类的身心只有极小部分得到了发挥 广义而言 xff0c 人类个体远未到达极限 人类囿于自身习惯 xff0c 从未将与生俱来的诸多能力发挥至极致 本书 xff0c
  • git-flow分支模型

    分支模型 xff1a 用 git flow 初始化工程目录完成后 xff0c 只能看到两个分支 xff08 长期分支 xff09 xff1a master 分支 xff1a 用于上线的分支 xff0c 保护性分支 xff0c 只包含经过测试
  • MySQL show关键字用法

    SHOW DATABASES 列出 MySQL Server 上的数据库 SHOW TABLES FROM db name 列出数据库中的表 SHOW TABLE STATUS FROM db name 列出数据库的表信息 xff0c 比较
  • windows10共享文件夹挂载到Ubuntu

    程序开发人员一般都会把开发目录放在windows系统下 xff0c 开发环境却是linux 以前我是linux下文件挂载到windows xff0c 有同事前车之鉴 xff0c 万一虚拟机linux挂壁了 xff0c 很难恢复 现在准备把w
  • 闭包函数中use使用

    匿名函数中的use xff0c 其作用就是从父作用域继承变量 下例是最常见的用法 xff0c 如果不使用use xff0c 函数中将找不到变量 msg 1 2 3 4 5 6 7 8 lt php msg 61 1 2 3 func