is_a和instanceof有什么区别?

Dan*_*iel 195 php

我知道这instanceof是一个操作员,这is_a是一种方法.

该方法的性能是否较慢?你更喜欢用什么?

irc*_*ell 207

实际上,is_a()是一个函数,而是is_a()一个语言结构. Object将显着更慢(因为它具有执行函数调用的所有开销),但在任一方法中总体执行时间都是最小的.

它从5.3开始不再被弃用了,所以不用担心.

但是有一个区别. $allow_string作为一个函数,一个对象作为参数1,一个字符串(变量,常量或文字)作为参数2.所以:

class MyBaseClass {}
class MyExtendingClass extends MyBaseClass {}

// Original behavior, evaluates to false.
is_a(MyExtendingClass::class, MyBaseClass::class);

// New behavior, evaluates to true.
is_a(MyExtendingClass::class, MyBaseClass::class, true);
Run Code Online (Sandbox Code Playgroud)

false 将对象作为参数1,并且可以将类名(变量),对象实例(变量)或类标识符(不带引号的类名称)作为参数2.

is_a($object, $string); // <- Only way to call it
Run Code Online (Sandbox Code Playgroud)

  • 关于`is_a`与`instanceof`运算符的另一个注意事项是`is_a`将接受第二个参数的表达式,而instanceof不会.例如`is_a($ object,'Prefix _'.$ name)``$ object instanceof'Prefix _'.$ name`不 (38认同)
  • 为什么`is_a`不推荐? (34认同)
  • @theodore-r-smith根据文档,它"已被流行的请求取消了"http://php.net/manual/en/migration53.undeprecated.php (20认同)
  • `is_a`从来就不应该被弃用.现在解决这个问题有点晚了.问题是`instanceof`运算符在PHP 4中引发语法错误,并且由于`is_a`在引入运算符的同时被弃用,因此无法在不抛出E_STRICT的情况下为PHP 4和5编写代码. .你甚至不能做`if(version_compare(PHP_VERSION,5)> = 0){/*使用instanceof*/} else {/*使用is_a*/}`因为它仍然会导致PHP 4中的语法错误. (6认同)
  • @danip` $ class ='Foo'; var_dump($ obj instanceof $ class);` (3认同)
  • 请注意,使用`is_a`,您必须在第二个参数上指定完整的命名空间,即使您使用`use`导入该类. (2认同)
  • “is_a 会明显变慢 [...],但两种方法的总体执行时间都很短。” 哈哈,是哪一个?许多开发人员有一个荒谬的想法,认为函数调用很慢,因此很糟糕。同时,这种比喻很少出现在 OOP 中,因为对象实例化比函数调用的最小开销贵一千倍,尤其是像“is_a()”这样微不足道的调用。这是迄今为止最普遍的过早优化的例子。太早了,以至于在编写一小部分代码之前就建议在注释中避免这样做。 (2认同)

Ale*_*ruk 46

以下是is_a()instanceof的性能结果:

Test name       Repeats         Result          Performance     
instanceof      10000           0.028343 sec    +0.00%
is_a()          10000           0.043927 sec    -54.98%
Run Code Online (Sandbox Code Playgroud)

测试源在这里.

  • 换句话说,只有在每10000次使用需要保存约0.015秒时,差异才很重要. (4认同)
  • @Toto 有一篇很棒的博客文章,介绍了经验丰富的开发人员可以向初学者学习什么。希望您能在右上角看到它。谨防过早优化!仅在时序问题成为问题之后才解决它们!如果性能可以接受,就不要花时间改变它! (4认同)
  • 从 `php 7` 开始,没有区别。 (2认同)
  • @CJDennis 当开发时间需要付出成本时,“避免过早优化”是一个很好的规则。在编写新代码时,您不妨牢记有关性能的最佳实践,尤其是当它们不需要任何额外工作时。 (2认同)

Lot*_*tes 10

instanceof可以与其他对象实例,类的名称或接口一起使用.我不认为它is_a()适用于接口(只是一个表示类名的字符串),但如果确实如此,请更正.(更新:请参阅https://gist.github.com/1455148)

来自php.net的示例:

interface MyInterface
{
}

class MyClass implements MyInterface
{
}

$a = new MyClass;
$b = new MyClass;
$c = 'MyClass';
$d = 'NotMyClass';

var_dump($a instanceof $b); // $b is an object of class MyClass
var_dump($a instanceof $c); // $c is a string 'MyClass'
var_dump($a instanceof $d); // $d is a string 'NotMyClass'
Run Code Online (Sandbox Code Playgroud)

输出:

bool(true)
bool(true)
bool(false)
Run Code Online (Sandbox Code Playgroud)

  • `is_a`使用与`instanceof`相同的方式使用接口(我会说同样的事情,但我在提交前检查过它,确实有效)... (3认同)
  • -1请总结更新,而不仅仅是链接到要点.这对于想要学习的人来说无益. (2认同)

Eri*_*ken 7

有一种情况,只有is_a()有效,instanceof才会失败。

instanceof需要一个字面类名或一个变量,该变量是对象或字符串(带有类名)作为其右参数。

但是,如果您想从函数调用中提供类名的字符串,它将不起作用并导致语法错误。

然而,同样的场景可以很好地使用is_a().

例子:

<?php

function getClassName() : string
{
    return "Foobar";
}

class Foobar
{
    private $xyz;

}

$x = new Foobar();

// this works of course
var_dump($x instanceof Foobar);

// this creates a syntax error
var_dump($x instanceof getClassName());

// this works
var_dump(is_a($x, getClassName()));
Run Code Online (Sandbox Code Playgroud)

这是基于 PHP 7.2.14 的。


Mik*_*ski 5

关于ChrisF的答案,从PHP 5.3.0开始is_a() 不再被弃用.我发现通过这样的事情的官方来源总是更安全.

关于你的问题,丹尼尔,我不能说性能差异,但部分内容将归结为可读性,你会发现它更容易使用.

此外,还有一些关于否定instanceof支票vs 的混淆的讨论is_a().例如,instanceof你会这样做:

<?php
if( !($a instanceof A) ) { //... }
?>
Run Code Online (Sandbox Code Playgroud)

以下为is_a():

<?php
if( !is_a($a, 'A' ) { //... }
?>
Run Code Online (Sandbox Code Playgroud)

要么

<?php
if( is_a($a, 'A') === FALSE) { //... }
?>
Run Code Online (Sandbox Code Playgroud)

编辑看起来像ChrisF删除了他的答案,但我的答案的第一部分仍然存在.


Cso*_*mai 5

除了速度之外,另一个重要的区别是它们如何处理边缘情况.

is_a($x1, $x2) // fatal error if x2 is not a string nor an object
$x1 instanceof $x2  // returns false even if $x2 is int, undefined, etc.
Run Code Online (Sandbox Code Playgroud)

因此,is_a()会突出显示可能的错误,而instanceof会抑制它们.