一只大脸猫博客主要分享PHP开发技巧、Web前端技术、网站优化、网站排名、修电脑、心灵鸡汤等一些生活中遇到的事、道理和技巧。分享更多知识给身边的朋友。
一只大脸猫博客主要分享PHP开发技巧、Web前端技术、网站优化、网站排名、修电脑、心灵鸡汤等一些生活中遇到的事、道理和技巧。分享更多知识给身边的朋友。

PHP 7新特性五 Spread operator(数组延展操作符)


在数组表达式中对展开操作符(Spread Operator)支持的 RFC 投票是 绝大多数人赞同 将此功能添加到 PHP 7.4。

扩展运算符支持参数解包首先存在于 PHP 5.6 中,并且此 RFC 扩展了对数组的使用;扩展可以支持 Traversable 的数组和对象。这是 RFC 的一个基本示例:

$parts = ['apple', 'pear'];
$fruits = ['banana', 'orange', ...$parts, 'watermelon'];// ['banana', 'orange', 'apple', 'pear', 'watermelon'];

/*以下是进一步的示例:*/

$arr1 = [1, 2, 3];
$arr2 = [...$arr1]; // [1, 2, 3]
$arr3 = [0, ...$arr1]; // [0, 1, 2, 3]
$arr4 = array(...$arr1, ...$arr2, 111); // [1, 2, 3, 1, 2, 3, 111]
$arr5 = [...$arr1, ...$arr1]; // [1, 2, 3, 1, 2, 3]

//定义函数
function getArr() {
  return ['a', 'b'];
}

$arr6 = [...getArr(), 'c']; // ['a', 'b', 'c']

$arr7 = [...new ArrayIterator(['a', 'b', 'c'])]; // ['a', 'b', 'c']

function arrGen() {
    for($i = 11; $i < 15; $i++) {
        yield $i;
    }
}
$arr8 = [...arrGen()]; // [11, 12, 13, 14]

函数调用中带有前缀的参数...将是“unpacked”:不是将参数本身传递给函数,而是传递它包含的元素(作为单独的参数)。这适用于数组和Traversables。

因此,以下所有函数调用都是等效的:

function test(...$args) { var_dump($args); }
 
test(1, 2, 3);                         // [1, 2, 3]
test(...[1, 2, 3]);                    // [1, 2, 3]
test(...new ArrayIterator([1, 2, 3])); // [1, 2, 3]
/*注意:解压缩像[1,2,3]这样的常量数组并没有多大意义。
通常这些会解压一些变量,比如... $ args*/
//可以...在调用中多次使用,并且可以在参数解包前使用普通参数:

$args1 = [1, 2, 3];
$args2 = [4, 5, 6];
test(...$args1, ...$args2); // [1, 2, 3, 4, 5, 6]
test(1, 2, 3, ...$args2);   // [1, 2, 3, 4, 5, 6]

//但是,在使用参数解包后,不可能使用普通参数。以下两个都是无效的:
//该...操作适用于所有的参数列表,包括new表达式:

fn(...$args);
$fn(...$args);
$obj->fn(...$args);
ClassName::fn(...$args);
new ClassName(...$args);

参数解包不仅限于可变参数函数,它还可以用于“普通”函数:

function test($arg1, $arg2, $arg3 = null) {
    var_dump($arg1, $arg2, $arg3);
}
 
test(...[1, 2]);       // 1, 2
test(...[1, 2, 3]);    // 1, 2, 3
test(...[1, 2, 3, 4]); // 1, 2, 3 (函数声明未捕获剩余的arg)

为了确保与命名参数的向前兼容性,解包操作符不支持字符串键。如果在解包期间遇到字符串键,则抛出可恢复的错误。如果使用自定义错误处理程序忽略错误,则不会解压缩其他参数,但仍会发生调用。

优于call_user_func_array的优点

call_user_func_array如果您还需要传递固定参数,则 使用会变得复杂。相比:

call_user_func_array([$db, 'query'], array_merge(array($query), $params));
// 对比
$db->query($query, ...$params);

call_user_func_array需要回调。因此,即使已知被调用的函数/方法,您仍然需要使用动态字符串/数组回调。这通常会排除任何IDE支持。

(new ReflectionClass('ClassName'))->newInstanceArgs($args);
// 对比
new ClassName(...$args);

call_user_func_array不适用于构造函数。而是ReflectionClass::newInstanceArgs()必须使用:

Futhermore call_user_func_array具有相当大的性能影响。如果大量的呼叫通过它,这可能会产生显着的差异。出于这个原因,项目1)经常用call_user_func_array以下形式的switch语句替换特别常见的调用:

switch (count($args)) {
    case 0: $func(); break;
    case 1: $func($args[0]); break;
    case 2: $func($args[0], $args[1]); break;
    case 3: $func($args[0], $args[1], $args[2]); break;
    case 4: $func($args[0], $args[1], $args[2], $args[3]); break;
    case 5: $func($args[0], $args[1], $args[2], $args[3], $args[4]); break;
    default: call_user_func_array($func, $args); break;
}

该...参数拆包语法比快约3.5至4倍call_user_func_args。这解决了性能问题。基准代码和结果。

最后,如果存在可变参数语法,人们自然希望这种语法存在。因此,如果我们实现可变参数,那么最好也包括它。


PHP 7新特性五 Spread operator(数组延展操作符):http://www.yzdlm.com/php/29.html

作者:吕宗国 分类: PHP博客


上一篇:为什么大家总喜欢黑PHP?PHP到底做错了什么 下一篇:Composer 是什么?

评论


乖,登录后才可以留言!
QQ一键登录
Top