我知道instanceof是一个操作符,is_a是一个方法。
该方法的性能是否较慢?你更喜欢用什么?
我知道instanceof是一个操作符,is_a是一个方法。
该方法的性能是否较慢?你更喜欢用什么?
当前回答
有一种情况是,只有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()));
这是基于PHP 7.2.14的。
其他回答
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'
输出:
bool(true)
bool(true)
bool(false)
更新
从PHP 5.3.9开始,is_a()的功能发生了变化。下面的原始答案指出,is_a()必须接受一个对象作为第一个参数,但PHP版本>= 5.3.9现在接受一个可选的第三个布尔参数$allow_string(默认为false),以允许比较字符串类名:
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);
instanceof和is_a()新行为的关键区别在于,instanceof将始终检查目标是否是指定类(包括扩展类)的实例化对象,而is_a()只要求在$allow_string参数设置为默认值false时实例化对象。
原始
实际上,is_a是一个函数,而instanceof是一个语言构造。Is_a将显著变慢(因为它具有执行函数调用的所有开销),但在这两种方法中,总体执行时间都是最小的。
从5.3版开始,它就不再被弃用了,所以不用担心。
但有一点不同。Is_a作为一个函数,以对象作为参数1,以字符串(变量、常量或文字)作为参数2。所以:
is_a($object, $string); // <- Only way to call it
Instanceof接受一个对象作为参数1,并且可以接受类名(变量)、对象实例(变量)或类标识符(不带引号的类名)作为参数2。
$object instanceof $string; // <- string class name
$object instanceof $otherObject; // <- object instance
$object instanceof ClassName; // <- identifier for the class
除了速度,另一个重要的区别是如何处理边缘情况。
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.
因此,is_a()突出显示可能的错误,而instanceof抑制它们。
下面是is_a()和instanceof的性能结果:
Test name Repeats Result Performance
instanceof 10000 0.028343 sec +0.00%
is_a() 10000 0.043927 sec -54.98%
测试源在这里。
关于ChrisF的回答,is_a()从PHP 5.3.0起不再弃用。我发现这种事还是听官方消息比较安全。
关于你的问题,丹尼尔,我不能说性能上的差异,但部分原因在于可读性,以及你觉得哪个更容易使用。
此外,还有一些关于否定instanceof check与is_a()的混淆的讨论。例如,instanceof你会这样做:
<?php
if( !($a instanceof A) ) { //... }
?>
Vs is_a():
<?php
if( !is_a($a, 'A' ) { //... }
?>
or
<?php
if( is_a($a, 'A') === FALSE) { //... }
?>
看起来ChrisF删除了他的答案,但我的答案的第一部分仍然有效。