JavaScript 与 PHP 中的闭包

Closure in JavaScript vs PHP

提问人:toni mora 提问时间:2/23/2022 最后编辑:toni mora 更新时间:2/23/2022 访问量:89

问:

我正在尝试在PHP中实现一个非常简单的闭包相关任务,但进展并不顺利。我在 JavaScript 中有这个解决方案。如何在PHP中实现它?

const data = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]

const getChunksOfTwo = () => {
  let pos = 0
  
  return () => {
     const start = pos
     const finish = start + 2
     const chunk = data.slice(start, finish)
     pos++
     return chunk
  }
}

// To initiate the closure
const closureFun = getChunksOfTwo()

// Call the closureFun
closureFun() // Gives [1, 2]
closureFun() // Gives [2, 3]
closureFun() // Gives [3, 4]

但是在PHP中,同样的情况显然是行不通的。我正在尝试这个:

$data = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];

function getChunksOfTwo($data) {
   $pos = 0;

   return function() {
     $start = $pos;
     $finish = $start + 2;
     $chunk = array_slice($data, $start, $finish);
     $pos++;
     return $chunk;
   };
};

// To initiate the closure
$closureFun = getChunksOfTwo($data);

// Call the closureFun
$closureFun(); // Does not give [1, 2]
$closureFun(); // Does not give [2, 3]

JavaScript PHP 闭包

评论

0赞 toni mora 2/23/2022
嗨,@ikhvjs,谢谢。是的,我忘了把它放在那里,但仍然不起作用。:(
1赞 Reyno 2/23/2022
您可以通过使用为内部函数提供对外部变量的访问权限。喜欢return function() use ($pos, $data) {}
0赞 ikhvjs 2/23/2022
@Reyno,你为什么不回答呢?
0赞 Reyno 2/23/2022
@ikhvjs 因为输出仍然不正确。
0赞 ikhvjs 2/23/2022
@Reyno,我明白了。那我就留下我的答案。:)

答:

-1赞 n1md7 2/23/2022 #1

你可以试试这个

$data = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];

function getChunksOfTwo($data) {
   $pos = 0;
   
   return function() use(&$pos, $data) {
     $start = $pos;
     $finish = 2;
     $chunk = array_slice($data, $start, $finish);
     $pos+=2;
     return $chunk;
   };
};

// To initiate the closure
$closureFun = getChunksOfTwo($data);

// Call the closureFun
print_r($closureFun()); // gives [1, 2]
print_r($closureFun()); // gives [2, 3]

$data = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];

function getChunksOfTwo($data) {
   $chunks = array_chunk($data, 2);
   $pos = 0;
   
   return function() use(&$pos, $data, $chunks) {
     return $chunks[$pos++];
   };
};

// To initiate the closure
$closureFun = getChunksOfTwo($data);

// Call the closureFun
print_r($closureFun()); // gives [1, 2]
print_r($closureFun()); // gives [2, 3]

&使用 var 表示通过引用传递

它必须通过引用传递才能改变该变量,否则它会复制原始变量,并且每个新调用都将具有相同的值。

奥普特

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

评论

0赞 Simone Rossaini 2/23/2022
输出错误。
0赞 toni mora 2/23/2022
感谢@n1md7,它很棒,但所有其他函数调用都在 arrray ''' 中添加额外的项目 数组 ( [0] => 1 [1] => 2 ) 数组 ( [0] => 2 [1] => 3 [2] => 4 ) 数组 ( [0] => 3 [1] => 4 [2] => 5 [3] => 6 ) '''
1赞 Reyno 2/23/2022
@tonimora 这是因为在 JS 中,该方法需要一个结束索引,而 PHP 需要一个长度。因此,只需将您的代码更改(在 PHP 中),它应该可以工作slice$finish = 2
0赞 toni mora 2/23/2022
伟大!谢谢。我对PHP很陌生,但这很有效。干杯!
2赞 ikhvjs 2/23/2022
@n1md7,问题不在于使用了错误的函数,而在于对函数的误解。最好让OP明白他为什么错了,而不是什么是对的。
0赞 Simone Rossaini 2/23/2022 #2

我提出了一个替代方案,为什么不使用?array_chunk

$data = [1,2, 3, 4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];
$chunk = array_chunk($data, 2);
$pos = 0;
print_r($chunk[$pos]);
$pos++;
print_r($chunk[$pos]);
$pos++;
print_r($chunk[$pos]);

输出:

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

参考:

评论

0赞 toni mora 2/23/2022
嗨,@Simone,非常感谢,但我需要根据增加的闭包值在内部函数内部调用一个函数,因此下面的解决方案对我有用。但很高兴了解array_chunk。非常感谢!
0赞 Simone Rossaini 2/24/2022
欢迎您:),如果您愿意,您可以+1仅供参考。
1赞 ikhvjs 2/23/2022 #3

您的代码中存在两个问题。php

首先是封装其范围的闭包,这意味着它无法访问定义或执行它的范围。但是,可以使用关键字将变量从父作用域(定义闭包的地方)继承到闭包中。这继承了变量,在闭包内使用其原始名称提供副本。PHPuseby-value

由于要保留每个函数调用的值,因此需要通过引用来传递它。$pos&$pos

其次,in 的实现方式与 in 不同。因此,您需要更改 php 中的输入。array_slicephpslicejs

<?php
$data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20];

function getChunksOfTwo($data) {
    $pos = 0;

    return function () use ($data, &$pos) {
        $chunk = array_slice($data, $pos, 2);
        $pos++;
        return $chunk;
    };
};

// To initiate the closure
$closureFun = getChunksOfTwo($data);

// Call the closureFun
print_r($closureFun());
print_r($closureFun());
print_r($closureFun());

评论

0赞 toni mora 2/23/2022
嗨,@ikhvjs,非常感谢。很好的答案和解释!:)
0赞 ikhvjs 2/23/2022
@tonimora,不客气。如果您认为这有帮助,请将其标记为答案。:)