• PHP8中字符串与数字的比较更智能


    PHP8.0发布[1]也有一段时间了,此次发布带来了很多实用且强大的功能,比如:

    1. Named arguments
    // php 7.x
    htmlspecialchars($string, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);
    
    // php 8.0
    htmlspecialchars($string, double_encode: false);
    

    传递参数时,可以通过指定参数名传递。

    1. Constructor property promotion
    // php 7.x
    class Point {
      public float $x;
      public float $y;
      public float $z;
    
      public function __construct(
        float $x = 0.0,
        float $y = 0.0,
        float $z = 0.0
      ) {
        $this->x = $x;
        $this->y = $y;
        $this->z = $z;
      }
    }
    
    // php 8.0
    class Point {
      public function __construct(
        public float $x = 0.0,
        public float $y = 0.0,
        public float $z = 0.0,
      ) {}
    }
    

    构造器参数向上提升,这个还挺有意思的,构造器中的参数(公众号 正义的程序猿)直接变成了类的属性,大大简化了代码量。

    1. Union types
    // php 7.x
    class Number {
      /** @var int|float */
      private $number;
    
      /**
       * @param float|int $number
       */
      public function __construct($number) {
        $this->number = $number;
        // 公众号 正义的程序猿
      }
    }
    
    new Number('NaN'); // Ok
    
    // php 8.0
    class Number {
      public function __construct(
        private int|float $number
      ) {}
    }
    
    new Number('NaN'); // TypeError
    

    在之前的版本,申明联合变量类型都是通(公众号 正义的程序猿)过注解的方式,而在8.0中,结合构造函数变量提升,直接在定义的时候申明联合类型,并且在8.0中是严格的,类型不匹配直接在运行时报错。

    当然,8.0中的feature不止这些,还有很多。这里来详细说一下Saner string to number comparisons,就是本文的标题。

    现象

    PHP中在比较时,我们经常这样操作:

    10 == '10'
    

    结果符合我们的预期,但这样并不是每次都正确,比如:

    // php 7.x
    0 == 'foobar' // true
      
    // php 8.0
    0 == 'foobar' // false
    

    是不是很诡异?

    再来一个:

    // php 7.x
    var_dump(in_array(0, ['foo', 'bar'])); // true
    
    // php 8.0
    var_dump(in_array(0, ['foo', 'bar'])); // false
    

    还有:

    // php 7.x
    $v = 0;
    
    switch ($v) {
        case 'bar':
            echo 'baaar' . PHP_EOL;
        case 0:
            echo 'foo' . PHP_EOL;
    }
    
    // 输出:
    // baaar
    // foo
    
    // PHP 8.0
    // 输出
    // foo
    

    为什么

    先来说一下PHP中的比较运算,分为两类,严格类型(===,!==)和非严格类型(==, !=, >, >=, 两者的主要区别如下:

    • 严格类型比较底层用的是strcmp(),非严格类型使用的是所谓的“智能”比较,即将字符串转为数字对比
    • 在比较数组时,严格类型不光会比较,还会比较索引的顺序,非严格类型只会简单的比较值
    • 在比较对象时,严格类型使用对象标识符比较,非严格类型只会比较对象的值

    在使用==比较数字字符串时,PHP 8.0之前的版本会先将字符串转换为数字,之后再做两个数字间的比较,这也就是为什么上门0 == "foobar" = true了。

    Saner string to number comparisons

    文章标题说PHP8中字符串与数字的比较更智能,具体智能在哪里?针对上面的问题,8.0当中引入Saner string to number comparisons这个特性[2],底层具体的操作为:当比较数字字符时,使用数字与数字对比,而其他字符与数字比较时,统一使用字符串比较。我们来通过一个表格来对比下前后的变化:

    Comparison    | Before | After
    ------------------------------
     0 == "0"     | true   | true
     0 == "0.0"   | true   | true
     0 == "foo"   | true   | false
     0 == ""      | true   | false
    42 == "   42" | true   | true
    42 == "42foo" | true   | false
    

    参考:

    1. https://www.php.net/releases/8.0/index.php
    2. https://wiki.php.net/rfc/string_to_number_comparison
  • 相关阅读:
    element-ui实现表格el-table展开行
    jQuery请求本地JSON文件,在谷歌浏览器运行时报跨域错误
    jQuery使用serialize获取form表单数据,中文乱码问题
    Element-ui局部添加loading效果
    Vue中this.$set的使用
    项目管理【81】 | 项目立项管理
    项目管理【80】 | 知识产权与标准规范-标准规范
    项目管理【79】 | 知识产权与标准规范-政府采购法法
    项目管理【78】 | 知识产权与标准规范-招投标法
    项目管理【77】 | 知识产权与标准规范-合同法
  • 原文地址:https://www.cnblogs.com/bilberry/p/14435599.html
Copyright © 2020-2023  润新知