A page showing some special JavaScript operators that make your code shorter and smarter.
JavaScript は、その他にもいくつかの演算子をサポートしています。以下、順に紹介しましょう。
条件演算子( ?: )は、JavaScript で唯一の三項演算子です。三項演算子というのは、オペランドを 3つ取るという意味です。この演算子は「 ?: 」と表記されますが、実際の使い方は少し違います。先頭のオペランドの後ろに「 ? 」を置き、その後ろに 2番目のオペランド、その後ろに「 : 」を置いて、最後に 3番目のオペランドを記述します。次の例を見てください。
JavaScript
x > 0 ? x : -x
// x の絶対値。
条件演算子のオペランドには任意の型の値を指定できます。先頭のオペランドが評価され、論理値として解釈されます。先頭のオペランドの値が true と評価できる場合は、2番目のオペランドの値を評価し、その値を返します。先頭のオペランドの値が false と評価できる場合は、3番目のオペランドの値を評価し、その値を返します。つまり、2番目のオペランドか、3番目のオペランドのいずれかのみが評価され、両方が評価されることはありません。
このやり方は if 文を使用しても実現できますが、?: 演算子のほうが簡単です。典型的な例は、変数が定義されているかどうか( true と評価される値を持つかどうか)をチャックし、定義されていればその値を使用し、定義されていなければデフォルトの値を使用する、という用法です。次の例を見てください。
JavaScript
greeting = "hello " + (username ? username : "there");
これと同じことは if 文でも可能ですが、条件演算子( ?: )を使用したほうが少ない行数で簡潔に記述できます。if 文の例を次に紹介します。
JavaScript
greeting = "hello ";
if (username)
greeting += username;
else
greeting += "there";
typeof は単項演算子です。オペランドは 1つだけです。オペランドの値は任意です。typeof 演算子は、オペランドのデータ型を示す文字列を返します。
typeof 演算子の使用例を紹介しておきます。
JavaScript
(typeof value == "string") ? "'" + value + "'" : value
typeof 演算子は、switch 文と組み合わせて使った場合も便利です。なお、typeof 演算子のオペランドを指定するときに、括弧( () )で囲んで指定することができます。このように記述すると、typeof は、演算子のキーワードではなく、関数名のように見えるかもしれません。
JavaScript
typeof(i)
オペランドの値が null の場合も、typeof は "object" という文字列を返すことに注意してください。null とオブジェクトを区別したい場合には、明示的に null かどうかをテストするようにしてください。typeof は、ホストオブジェクトに対して "object" 以外の文字列を返す場合があります。しかし、実際には、クライアントサイド JavaScript 中のホストオブジェクトの大半は、"object" という型を持ちます。
オペランドが関数以外のオブジェクトと配列の場合、typeof 演算子は "object"(オブジェクト型)としか返さないので、オブジェクト型とその他の基本型とを区別することしか出来ません。どのオブジェクト型であるのかを知るには、別の手法が必要です。例えば、instanceof 演算子(「関係演算子」を参照)やクラス属性、constructor プロパティを使います。
JavaScript では、関数はオブジェクトの一種ですが、関数は戻り値を持つので、ほかのオブジェクトとは異なると判断し、typeof 演算子は "function" という文字列を返します。JavaScript では、関数と「呼び出し可能なオブジェクト」とを微妙に区別します。すべての関数は呼び出し可能です。一方で、呼び出し可能なオブジェクトは、本当の意味では関数ではありませんが、関数と同じように呼び出すこともできます。ECMAScript 3 では、呼び出し可能なネイティブオブジェクトについては、すべて "function" を返すように規定しています。ECMAScript 5 仕様では、この仕様を拡張して、ネイティブオブジェクトでもホストオブジェクトでも呼び出し可能なオブジェクト全てに対して、typeof は "function" という文字列を返すように規定しています。多くのブラウザでは、ホストオブジェクトのメソッドとして JavaScript の関数オブジェクトを使っています。しかし、Microsoft 社は、クライアントサイド用のメソッドとしては、呼び出し可能なオブジェクトを使うようにしています。IE9 より前の IE では、typeof 演算子は、このような呼び出し可能なオブジェクトに対して "object" という文字列を返します。IE9 では、クライアントサイドメソッドは、関数オブジェクトになっています。本当の関数と呼び出し可能なオブジェクトとの違いについては、別ページで説明予定です。
delete 演算子は単項演算子で、オペランドに指定された「オブジェクトのプロパティ」や「配列の要素」を削除します。
名前が同じでも、C++ の delete 演算子とは全く別物です。JavaScript ではメモリ管理は自動(ガーベジコレクション)なので、メモリを直接解放するために delete を使う必要はありません。
delete は、指定されたプロパティを削除する副作用のために使われるのが一般的です。
JavaScript
let obj = { x: 1, y: 2 };
console.log("x" in obj); // true
delete obj.x; // プロパティを削除
console.log("x" in obj); // false
プロパティを削除すると、単に undefined が代入されるのではなく、そのプロパティ自体が「存在しなくなります」。存在チェックには in 演算子を使います。
delete を配列に使うと、指定した要素が「空(empty)」になるだけで、配列の長さ(length)は変わりません。削除ではなく「穴があく」イメージです。
JavaScript
let arr = [1, 2, 3];
delete arr[1];
console.log(arr); // [1, empty, 3]
console.log(arr.length); // 3(長さは変わらない)
要素を詰めたい場合は splice() を使うとよいでしょう。
JavaScript
arr.splice(1, 1);
console.log(arr); // [1, 3]
delete で削除できるのは「プロパティ」や「配列要素」だけです。var で宣言した変数や function で定義した関数は削除できません。
JavaScript
var x = 1;
console.log(delete x); // false(削除できない)
this.y = 2;
console.log(delete this.y); // true(プロパティなら削除可能)
strict モードでは、削除できない対象(変数・再定義不可のプロパティなど)を削除しようとすると、TypeError が発生します。
JavaScript
'use strict';
var z = 10;
delete z; // TypeError: Delete of an unqualified identifier in strict mode.
非 strict モードでは、このような削除は失敗しても例外は出ず、単に false が返されます。
void は単項演算子です。オペランドとしては任意の値が取れます。void 演算子は、あまり使われるものではありません。void 演算子は、オペランド値を廃棄し未定義値を返すという特殊なものだからです。オペランド値を廃棄するので、void 演算子は使って意味のある場合は、オペランドが副作用を持つときだけです。
実際に void 演算子を使用する場面は、クライアントサイド JavaScript の javascript: URL 中くらいでしょう。式を評価する際の副作用は期待するが、式を評価した結果の値をブラウザが表示するのは望まない場合に使用します。HTML での使用例を以下に紹介しておきます。
JavaScript
<a href="javascript:void window.open();">Open New Window</a>
HTML では、javascript: URL を使わなくても、onclick イベントハンドラを使えば、もっと明確に記述できます。イベントハンドラを使う場合は、もちろん void 演算子は必要ありません。
カンマ( , )演算子は二項演算子です。オペランドには任意の型の値を指定できます。まず左側のオペランドを評価し、次に右側のオペランドを評価し、最後に右側のオペランドの値を返します。次の例を見てください。
JavaScript
i=0, j=1, k=2;
この式を評価すると 2 になります。上記のコードは次のように書いても同じです。
JavaScript
i = 0; j = 1; k = 2;
左側の式は評価されますが、値は捨てられます。つまり、カンマ演算子を使って意味があるのは、左側の式に副作用がある場合だけです。カンマ演算子が使われるのは、for ループで複数のループ変数を使う時が一般的です。例を示します。
JavaScript
// 以下の例の最初のカンマは、var 文の構文の一部。
// 2つ目のカンマがカンマ演算子。カンマ演算子で、2つの式( i++ と j-- )を
// 1つの式しか受け付けない文( for ループ)中に記述。
for(var i=0,j=10; i < j; i++,j--)
console.log(i+j);