Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1176352
  • 博文数量: 252
  • 博客积分: 5421
  • 博客等级: 大校
  • 技术积分: 2418
  • 用 户 组: 普通用户
  • 注册时间: 2007-06-17 12:59
文章分类

全部博文(252)

文章存档

2017年(3)

2016年(18)

2015年(31)

2014年(18)

2013年(7)

2012年(8)

2011年(12)

2010年(30)

2009年(32)

2008年(57)

2007年(36)

分类: PHP

2015-10-23 21:39:36


  1. <?php
  2. function getClosure($i)
  3. {
  4.         $i = $i.'-'.date('H:i:s');
  5.         return function ($param) use ($i) {
  6.                 echo "--- param: $param ---\n";
  7.                 echo "--- i: $i ---\n";
  8.         };
  9. }

  10. $c = getClosure(123);
  11. $i = 456;
  12. $c('test');
  13. sleep(3);
  14. $c2 = getClosure(123);
  15. $c2('test');
  16. $c('test');


  17. /*
  18. output:
  19. --- param: test ---
  20. --- i: 123-21:36:52 ---
  21. --- param: test ---
  22. --- i: 123-21:36:55 ---
  23. --- param: test ---
  24. --- i: 123-21:36:52 ---
  25. */
如上,闭包中使用use声明的变量来自于生成闭包实例时所在作用域内的同名变量,而不是来自于运行闭包时所在作用域内的同名变量。而闭包的函数参数则是和正常的函数参数一样来自于运行时所在作用域内的同名变量。

以下为opcode:

  1. Finding entry points
  2. Branch analysis from position: 0
  3. Jump found. Position 1 = -2
  4. filename: /tmp/testclosure.php
  5. function name: (null)
  6. number of ops: 20
  7. compiled vars: !0 = $c, !1 = $i, !2 = $c2
  8. line #* E I O op fetch ext return operands
  9. -------------------------------------------------------------------------------------
  10.    2 0 E > NOP
  11.   11 1 SEND_VAL 123
  12.          2 DO_FCALL 1 $0 'getclosure'
  13.          3 ASSIGN !0, $0
  14.   12 4 ASSIGN !1, 456
  15.   13 5 INIT_FCALL_BY_NAME !0
  16.          6 SEND_VAL 'test'
  17.          7 DO_FCALL_BY_NAME 1
  18.   14 8 SEND_VAL 3
  19.          9 DO_FCALL 1 'sleep'
  20.   15 10 SEND_VAL 123
  21.         11 DO_FCALL 1 $5 'getclosure'
  22.         12 ASSIGN !2, $5
  23.   16 13 INIT_FCALL_BY_NAME !2
  24.         14 SEND_VAL 'test'
  25.         15 DO_FCALL_BY_NAME 1
  26.   17 16 INIT_FCALL_BY_NAME !0
  27.         17 SEND_VAL 'test'
  28.         18 DO_FCALL_BY_NAME 1
  29.   29 19 > RETURN 1

  30. Function %00%7Bclosure%7D%2Ftmp%2Ftestclosure.php0x7fb0115f505:
  31. Finding entry points
  32. Branch analysis from position: 0
  33. Jump found. Position 1 = -2
  34. filename: /tmp/testclosure.php
  35. function name: {closure}
  36. number of ops: 12
  37. compiled vars: !0 = $param, !1 = $i
  38. line #* E I O op fetch ext return operands
  39. -------------------------------------------------------------------------------------
  40.    5 0 E > RECV !0
  41.          1 FETCH_R static $0 'i'
  42.          2 ASSIGN !1, $0
  43.    6 3 ADD_STRING ~2 '---+param%3A+'
  44.          4 ADD_VAR ~2 ~2, !0
  45.          5 ADD_STRING ~2 ~2, '+---%0A'
  46.          6 ECHO ~2
  47.    7 7 ADD_STRING ~3 '---+i%3A+'
  48.          8 ADD_VAR ~3 ~3, !1
  49.          9 ADD_STRING ~3 ~3, '+---%0A'
  50.         10 ECHO ~3
  51.    8 11 > RETURN null

  52. End of function %00%7Bclosure%7D%2Ftmp%2Ftestclosure.php0x7fb0115f505

  53. Function getclosure:
  54. Finding entry points
  55. Branch analysis from position: 0
  56. Jump found. Position 1 = -2
  57. filename: /tmp/testclosure.php
  58. function name: getClosure
  59. number of ops: 9
  60. compiled vars: !0 = $i
  61. line #* E I O op fetch ext return operands
  62. -------------------------------------------------------------------------------------
  63.    2 0 E > RECV !0
  64.    4 1 CONCAT ~0 !0, '-'
  65.          2 SEND_VAL 'H%3Ai%3As'
  66.          3 DO_FCALL 1 $1 'date'
  67.          4 CONCAT ~2 ~0, $1
  68.          5 ASSIGN !0, ~2
  69.    5 6 DECLARE_LAMBDA_FUNCTION '%00%7Bclosure%7D%2Ftmp%2Ftestclosure.php0x7fb0115f5051'
  70.    8 7 > RETURN ~4
  71.    9 8* > RETURN null

  72. End of function getclosure
如上,闭包函数的op_array(相当于类定义)在编译期完成,但在运行期生成闭包实例(相当于类实例)时会为不同实例绑定不同的use静态变量(在DECLARE_LAMBDA_FUNCTION中完成)。
阅读(824) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~