ブログ
11.182016
条件式の「==」と「===」の意味と違いの3つのポイント
WordPressの内部プログラムはPHPというプログラミング言語で実装されています。
PHPでは条件分岐などの条件式で等号や不等号などを使用すると思います。
条件式で用いる左右の値の大小や一致関係を確認する演算子は「比較演算子」と呼ばれていて、演算子の左右に置いた値(リテラル値)や変数の内容の比較をそれぞれ以下のような役割で担当しています。
演算子 | 役割 |
---|---|
== | 等しい |
!= | 等しくない |
> | より多い |
>= | より多いか等しい(以上) |
< | より少ない(未満) |
<= | より少ないか等しい(以下) |
基本的にはこれらの演算子で全てですが、PHP では一致の「==」と不一致の「!=」に別パターンで「===」と「!==」があります。
C 言語系の他のプログラミング言語から WordPress の世界や PHP の世界に来られた方には謎ともいえるこの演算子ですが、一致しているか不一致であるかを比較するという点を除いては厳密には全く意味が違っていて、適切な使い方をしなければ誤った動作を引き起こしかねない演算子となっています。
今回は、なんとなく混同しやすいこれらの演算子のみを取り上げ、「意味」「動作」「速度」の3つの観点からご紹介します。
意味の違い
「===」と「!==」の等号や不等号は、値と「データ型」まで含めた完全一致か不完全一致かを判定します。
データ型とは、データの種類のことですが、簡単に言えば、文字、数値(整数)、数値(実数=小数点を含む値)、論理(TrueかFalseか、YesかNoか、真か偽か)といったデータの性格です。たとえば数値としての「123」は整数として扱いますし、画面に表示されるような文字「abc」は文字として扱います。ですので、文字としての「123」は文字として扱うという具合です。
他の固めのプログラム言語では比較的常識でもあるこの概念ですが、PHP では非常に弱いデータ型を持っているという特徴があり、データ型の情報はそれぞれ持っているものの、特定のデータ型専用の変数を作ることができず、汎用的にどのデータ型のデータでも変数に代入することができてしまう仕様となっています。
この仕様を補うためでもあるのでしょう、等号や不等号についても他言語と同様の「==」や「!=」はデータ型は無視し、内容が一致しているかまたは不一致であるかを返すという仕様になっています。
他の言語では当然のことができないのですが、緩いながらも存在するデータ型も含めて完全に一致しているかまたは不一致であるかを判定する比較演算子が「===」と「!==」になっているわけです。
動作の違い
動作の違いをサンプルを交えて説明します。
2つの変数にそれぞれデータを代入し、比較した結果を var_dump() 関数で出力します。
$a = 123; $b = 123; echo '$a == $b : '; var_dump($a == $b); echo '$a === $b : '; var_dump($a === $b); echo '$a != $b : '; var_dump($a != $b); echo '$a !== $b : '; var_dump($a !== $b);
まずは2つの変数に同じ値を代入した場合ですが、こちらはいずれの比較演算子でも変わらない結果となっています。
$a = 123; $b = "123"; echo '$a == $b : '; var_dump($a == $b); echo '$a === $b : '; var_dump($a === $b); echo '$a != $b : '; var_dump($a != $b); echo '$a !== $b : '; var_dump($a !== $b);
一方で、「”123″」とダブルクォーテーションで囲った方は文字列として代入されているため、判定結果も仕様通り「===」で比較した方は「false」すなわち条件を満たしていないという結果を返しています。
データ型を含めて比較するということはこのような結果の差を生み出すこととなります。
この違いは論理値の比較で特に問題が生じやすく、不具合の原因となりやすいケースがあります。以下の例ではそのようなケースについて等号の方のみですがパターン分けして紹介します。
trueと数字の1を比較した場合
$a = true; $b = 1; echo '$a == $b : '; var_dump($a == $b); echo '$a === $b : '; var_dump($a === $b);
trueと文字列Aを比較した場合
$a = true; $b = "A"; echo '$a == $b : '; var_dump($a == $b); echo '$a === $b : '; var_dump($a === $b);
falseと数値の0を比較した場合
$a = false; $b = 0; echo '$a == $b : '; var_dump($a == $b); echo '$a === $b : '; var_dump($a === $b);
falseと空の文字列を比較した場合
$a = false; $b = ""; echo '$a == $b : '; var_dump($a == $b); echo '$a === $b : '; var_dump($a === $b);
このように、真は「true」以外にも何らかの値があるとき、偽は「false」以外にも「0」や空の文字列でも「==」では成立し、「===」では不成立となるという差があります。
論理型(boolean型)で真偽で判定を行うケースでは、実装の際はより慎重な判断の上で行うことをオススメします。
速度の違い
まずは速度について、以下のサンプルプログラムを複数回動かした際の結果と平均値を示します。
純粋に比較だけを行うために、比較関数のみを動かすプログラムを100万回した結果で見ていきます。
データ型が異なっているケース
サンプルプログラムは以下の通りです。
こちらは8行目の演算子が「===」のパターンの例ですが、その部分を「==」「!==」「!=」に置き換えて実行しています。
<?php $a = 1; $b = "1"; $time_begin = microtime(true); for ($i = 0; $i < 1000000; $i++) { if($a === $b); } $time_end = microtime(true); $time = $time_end - $time_begin; print "exec time = ${time} sec.";
データ型まで一致しているケース
データ型が不一致のケースのプログラムから、変数「$b」の値の設定を変更し、両方とも数値となるようにしています。
先ほどと同様に、8行目の演算子が「===」のパターンの例ですが、その部分を「==」「!==」「!=」に置き換えて実行しています。
<?php $a = 1; $b = 1; $time_begin = microtime(true); for ($i = 0; $i < 1000000; $i++) { if($a === $b); } $time_end = microtime(true); $time = $time_end - $time_begin; print "exec time = ${time} sec.";
計測結果
データ一致の場合
(秒) | == | != | === | !== |
---|---|---|---|---|
1回目 | 0.24242496490479 | 0.24050903320312 | 0.12385392189026 | 0.13044500350952 |
2回目 | 0.23953509330750 | 0.24440407752991 | 0.12304997444153 | 0.13942909240723 |
3回目 | 0.24601912498474 | 0.24477195739746 | 0.12033319473267 | 0.13987898826599 |
平均 | 0.24265972773234 | 0.24322835604350 | 0.12241236368815 | 0.13658436139425 |
データ不一致の場合
(秒) | == | != | === | !== |
---|---|---|---|---|
1回目 | 0.20984697341919 | 0.17770290374756 | 0.12873101234436 | 0.12670397758484 |
2回目 | 0.21555089950562 | 0.17612004280090 | 0.12640595436096 | 0.13187289237976 |
3回目 | 0.19957685470581 | 0.17382693290710 | 0.12833714485168 | 0.13346791267395 |
平均 | 0.20832490921021 | 0.17588329315185 | 0.12782470385233 | 0.13068159421285 |
このように、速度だけであれば「===」と「!==」が早い結果となります。
計測結果からは、1.3~2倍程度の速度改善が見られます。今回は100万回の実行結果でこの程度の差であるため、大きな差とまでは言えませんが、回数が増すごとに効果が大きく開いてくるということになります。
この差は、データ型の比較を含まない「==」と「!=」ではデータ型を比較演算子の左辺のものに変換するという手順を踏むため、その分の時間がオーバーヘッドとして乗ってしまうため結果として時間が掛かるものとなります。本来であれば変換が不要な場合でもデータ型の確認を行うなどの手続きがあるのだと考えられますが同様の傾向がみられます。
まとめ
微妙な差ではあるのですが、プログラムでは膨大な回数の比較が行われるため、より速度を重視し効率的なプログラミングを行ったり、無駄でミスの少ない実装を行うためにはぜひこの差を知った上で選んで頂ければと思います。
Copyright © PLUGMIZE(プラグマイズ)