HTML5テクニカルノート
if文なしに論理演算子で条件判定の処理をする
- ID: FN1803004
- Technique: HTML5 / ECMAScript 2015
演算子の論理和||
や論理積&&
は、ほとんどの場合if
文などの分岐処理に条件として使われます。けれど、これらの論理演算子だけで条件判定の処理ができることもあるのです。理解するためには、論理演算子の正確な働きを知っておかなければなりません。
01 初期化されていない変数にデフォルト値を与える
変数がまだ値をもっていないとき、デフォルト値を加えたいことがあります。たとえば、ユーザーがまだテキストを入力していないときに、デフォルトの文字列を変数に入れる場合です。変数に値がなかったり、空文字列""が納められていると、ブール(論理)値としての評価はfalse
になります。したがって、if
文では以下のようなJavaScriptコードを書けばよいでしょう。
もし、変数(input)の値が未定義(undefined
)または空文字列""であれば、ブール値評価された値false
が論理否定演算子!
によりtrue
に反転します。したがって、この場合には変数にデフォルト値が与えられることになります。すでに変数に文字列が納められていたら、値はそのまま変わりません。
if (!input) { input = "デフォルト値"; }
同じ処理は、つぎのように条件演算子?:
を使ってもできます。変数(input)に空文字列""以外の文字列が入っていれば、その値が改めて変数に代入されます。そうでない場合には、変数にデフォルト値が納められることになります。
input = input ? input : "デフォルト値";
論理和演算子||
を使うとさらに短く書けます。この処理を理解するには、オペランド(被演算子)の式の評価がブール値であっても、返すのは式の値そのものであることを知らなければなりません。つぎの構文で、論理和演算子||
は式1をブール値評価して、true
なら式1、そうでなければ式2の値を返すのです(表001)。
式1 || 式2
表001■論理和演算子||のオペランドの評価と戻り値
式1の評価 | 戻り値 |
---|---|
true
|
式1の値 |
false
|
式2の値 |
変数(input)に空文字列""でない文字列が入っていれば、論理和演算子||の左オペランドのブール値評価はtrue
です。その場合に変数に代入される戻り値は左オペランドそのものの値、つまり中に入っている文字列になります。そして、左オペランドがfalse
と評価されると、右オペランドはもはやブール値評価されることなく、その値がそのまま返るのです。したがって、変数にはデフォルト値が納められます。
input = input || "デフォルト値";
関数の引数にも、同じやり方でデフォルト値が与えられます。
function getPoint(x, y) { x = x || 0; y = y || 0; return {x: x, y: y}; } console.log(getPoint()); // {x: 0, y: 0}
ECMAScript 2015 (ECMAScript 6)から、関数にはデフォルト引数が定められるようになりました。この構文を用いれば、もっと簡単に引数にデフォルト値が与えられます。
function getPoint(x = 0, y = 0) { return {x: x, y: y}; }
02 関数があることを確かめて呼出す
関数を引数に渡したり、コールバックに定めると、関数を書き替えるだけで処理がさまざまに変えられます。なお、つぎのコードではアロー関数式=>
(ECMAScript 2015)とべき乗演算子**
(ECMAScript 2016を用いています。
function getPoint(x, y, func) { const point = {x: x, y: y}; func(point); return point; } const point = getPoint(3, 4, (point) => { point.x **= 2; point.y **= 2; }); console.log(point); // {x: 9, y: 16}
もっとも、呼びだす関数が与えられていなければ、エラーになってしまいます。
const point2 = getPoint(1, 2); // Uncaught TypeError: func is not a function
関数が与えられなくてもエラーにならないようにするには、呼び出す前に関数があるかどうか確かめなければなりません。if
文で書けば、つぎのようなJavaScriptコードになります。条件に定めた引数に関数がなければ値はundefined
ですので、条件としての評価がfalse
となって呼出しは行われません。関数があれば、オブジェクトはtrue
と評価されるため、関数が呼出されます。
function getPoint(x, y, func) { const point = {x: x, y: y}; if (func) { func(point); } return point; }
同じ判定の処理は、論理積演算子&&
を使ってさらに短く書けます。この演算子も論理和と同じく、左オペランドのブール値評価により、返される値が変わるのです。式1の評価がtrue
なら式2、そうでなければ式1の値が返されます(表002)。
式1 && 式2
表002■論理積演算子&&のオペランドの評価と戻り値
式1の評価 | 戻り値 |
---|---|
true
|
式2の値 |
false
|
式1の値 |
引数に関数が渡されたかどうか、論理積演算子&&
で確かめてから呼び出すのがつぎのコードです。注目されることに、if
文が使われていないだけでなく、演算子の戻り値さえ省みられていません。鍵となるのは、左オペランドをfalse
と評価したときの演算子のふるまいです(前掲表002参照)。その場合、戻り値も左オペランドですので、右オペランドは見向きもされません。つまり、呼び出されないということです。左オペランドの評価がtrue
のときはじめて、右オペランドは戻り値として参照されます。このとき呼び出しが起こり、戻り値そのものはどこにも使われないのです。
function getPoint(x, y, func) { const point = {x: x, y: y}; func && func(point); return point; } const point = getPoint(3, 4, (point) => { point.x **= 2; point.y **= 2; }); console.log(point); // {x: 9, y: 16} const point2 = getPoint(1, 2); console.log(point2); // {x: 1, y: 2}
もう少しつっこむと、ブール値で評価されるのはオブジェクトのあるなしだけです。あえて関数でないオブジェクトを渡せば、やはりエラーが起こります。
const point2 = getPoint(1, 2, {}); // Uncaught TypeError: func is not a function
関数であることまで確かめなければならない場合には、併せてinstanceof
演算子を用いればよいでしょう。
function getPoint(x, y, func) { const point = {x: x, y: y}; (func instanceof Function) && func(point); return point; }
作成者: 野中文雄
作成日: 2018年3月17日「論理演算子を使った条件判定」を全面改訂。
Copyright © 2001-2018 Fumio Nonaka. All rights reserved.