php闭包中使用use声明变量的作用域实例分析


Posted in PHP onAugust 09, 2018

本文实例讲述了php闭包中使用use声明变量的作用域。分享给大家供大家参考,具体如下:

<?php
function getClosure($i)
{
    $i = $i.'-'.date('H:i:s');
    return function ($param) use ($i) {
        echo "--- param: $param ---\n";
        echo "--- i: $i ---\n";
    };
}
$c = getClosure(123);
$i = 456;
$c('test');
sleep(3);
$c2 = getClosure(123);
$c2('test');
$c('test');
/*
output:
--- param: test ---
--- i: 123-21:36:52 ---
--- param: test ---
--- i: 123-21:36:55 ---
--- param: test ---
--- i: 123-21:36:52 ---
*/

如上,闭包中使用use声明的变量来自于生成闭包实例时所在作用域内的同名变量,而不是来自于运行闭包时所在作用域内的同名变量。

而闭包的函数参数则是和正常的函数参数一样来自于运行时所在作用域内的同名变量。

以下为opcode:

Finding entry points
Branch analysis from position: 0
Jump found. Position 1 = -2
filename:       /tmp/testclosure.php
function name:  (null)
number of ops:  20
compiled vars:  !0 = $c, !1 = $i, !2 = $c2
line     #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
   2     0  E >   NOP
  11     1        SEND_VAL                                                 123
         2        DO_FCALL                                      1  $0      'getclosure'
         3        ASSIGN                                                   !0, $0
  12     4        ASSIGN                                                   !1, 456
  13     5        INIT_FCALL_BY_NAME                                       !0
         6        SEND_VAL                                                 'test'
         7        DO_FCALL_BY_NAME                              1
  14     8        SEND_VAL                                                 3
         9        DO_FCALL                                      1          'sleep'
  15    10        SEND_VAL                                                 123
        11        DO_FCALL                                      1  $5      'getclosure'
        12        ASSIGN                                                   !2, $5
  16    13        INIT_FCALL_BY_NAME                                       !2
        14        SEND_VAL                                                 'test'
        15        DO_FCALL_BY_NAME                              1
  17    16        INIT_FCALL_BY_NAME                                       !0
        17        SEND_VAL                                                 'test'
        18        DO_FCALL_BY_NAME                              1
  29    19      > RETURN                                                   1
Function %00%7Bclosure%7D%2Ftmp%2Ftestclosure.php0x7fb0115f505:
Finding entry points
Branch analysis from position: 0
Jump found. Position 1 = -2
filename:       /tmp/testclosure.php
function name:  {closure}
number of ops:  12
compiled vars:  !0 = $param, !1 = $i
line     #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
   5     0  E >   RECV                                             !0
         1        FETCH_R                      static              $0      'i'
         2        ASSIGN                                                   !1, $0
   6     3        ADD_STRING                                       ~2      '---+param%3A+'
         4        ADD_VAR                                          ~2      ~2, !0
         5        ADD_STRING                                       ~2      ~2, '+---%0A'
         6        ECHO                                                     ~2
   7     7        ADD_STRING                                       ~3      '---+i%3A+'
         8        ADD_VAR                                          ~3      ~3, !1
         9        ADD_STRING                                       ~3      ~3, '+---%0A'
        10        ECHO                                                     ~3
   8    11      > RETURN                                                   null
End of function %00%7Bclosure%7D%2Ftmp%2Ftestclosure.php0x7fb0115f505
Function getclosure:
Finding entry points
Branch analysis from position: 0
Jump found. Position 1 = -2
filename:       /tmp/testclosure.php
function name:  getClosure
number of ops:  9
compiled vars:  !0 = $i
line     #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
   2     0  E >   RECV                                             !0
   4     1        CONCAT                                           ~0      !0, '-'
         2        SEND_VAL                                                 'H%3Ai%3As'
         3        DO_FCALL                                      1  $1      'date'
         4        CONCAT                                           ~2      ~0, $1
         5        ASSIGN                                                   !0, ~2
   5     6        DECLARE_LAMBDA_FUNCTION                                  '%00%7Bclosure%7D%2Ftmp%2Ftestclosure.php0x7fb0115f5051'
   8     7      > RETURN                                                   ~4
   9     8*     > RETURN                                                   null
End of function getclosure

如上,闭包函数的op_array(相当于类定义)在编译期完成,但在运行期生成闭包实例(相当于类实例)时会为不同实例绑定不同的use静态变量(在DECLARE_LAMBDA_FUNCTION中完成)。

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
PHP5 安装方法
Oct 09 PHP
php横向重复区域显示二法
Sep 25 PHP
PHP程序61条面向对象分析设计的经验小结
Nov 12 PHP
php.ini中date.timezone设置分析
Jul 29 PHP
PHP中extract()函数的妙用分析
Jul 11 PHP
php面向对象中的魔术方法中文说明
Mar 04 PHP
简单谈谈php延迟静态绑定
Jan 26 PHP
PHP入门教程之面向对象基本概念实例分析
Sep 11 PHP
PHP删除数组中指定下标的元素方法
Feb 03 PHP
Yii2.0建立公共方法简单示例
Jan 29 PHP
PHP实现与java 通信的插件使用教程
Aug 11 PHP
PHP7 错误处理机制修改
Mar 09 PHP
php生成二维码不保存服务器还有下载功能的实现代码
Aug 09 #PHP
PHP命令Command模式用法实例分析
Aug 08 #PHP
PHP耦合设计模式实例分析
Aug 08 #PHP
thinkPHP框架整合tcpdf插件操作示例
Aug 07 #PHP
php实现往pdf中加数字签名操作示例【附源码下载】
Aug 07 #PHP
php使用环形链表解决约瑟夫问题完整示例
Aug 07 #PHP
postman的安装与使用方法(模拟Get和Post请求)
Aug 06 #PHP
You might like
桌面中心(三)修改数据库
2006/10/09 PHP
PHP4.04简明安装
2006/10/09 PHP
php时间不正确的解决方法
2008/04/09 PHP
php &amp;&amp; 逻辑与运算符使用说明
2010/03/04 PHP
phpMyAdmin 链接表的附加功能尚未激活的问题
2010/08/01 PHP
php格式化电话号码的方法
2015/04/24 PHP
[原创]PHP实现字节数Byte转换为KB、MB、GB、TB的方法
2017/08/31 PHP
PHP后台备份MySQL数据库的源码实例
2019/03/18 PHP
HTML TO JavaScript 转换
2006/06/26 Javascript
TextArea设置MaxLength属性最大输入值的js代码
2012/12/21 Javascript
下拉菜单点击实现连接跳转功能的js代码
2013/05/19 Javascript
jQuery防止click双击多次提交及传递动态函数或多参数
2014/04/02 Javascript
JS的encodeURI和java的URLDecoder.decode使用介绍
2014/05/08 Javascript
js简单获取表单中单选按钮值的方法
2016/08/23 Javascript
jQuery插件FusionCharts实现的3D柱状图效果实例【附demo源码下载】
2017/03/03 Javascript
js中编码函数:escape,encodeURI与encodeURIComponent详解
2017/03/21 Javascript
jQuery查找dom的几种方法效率详解
2017/05/17 jQuery
vue-router history模式下的微信分享小结
2018/07/05 Javascript
关于JavaScript中异步/等待的用法与理解
2020/11/18 Javascript
[10:42]Team Liquid Vs Newbee
2018/06/07 DOTA
对python 矩阵转置transpose的实例讲解
2018/04/17 Python
win7 x64系统中安装Scrapy的方法
2018/11/18 Python
解决python字典对值(值为列表)赋值出现重复的问题
2019/01/20 Python
python做接口测试的必要性
2019/11/20 Python
Python @property及getter setter原理详解
2020/03/31 Python
突袭HTML5之Javascript API扩展5—其他扩展(应用缓存/服务端消息/桌面通知)
2013/01/31 HTML / CSS
Theflamel意大利:女士奢华服装、鞋子和配件
2020/01/11 全球购物
竞争上岗演讲稿
2014/01/05 职场文书
最新大学生创业计划书写作攻略
2014/04/02 职场文书
2014教师党员自我评议总结
2014/09/19 职场文书
2015年收银员个人工作总结
2015/04/01 职场文书
企业战略合作意向书
2015/05/08 职场文书
Java中使用Filter过滤器的方法
2021/06/28 Java/Android
Maven学习----Maven安装与环境变量配置教程
2021/06/29 Java/Android
Java日常练习题,每天进步一点点(38)
2021/07/26 Java/Android
java executor包参数处理功能 
2022/02/15 Java/Android