HTML Living Standard  第3部 Javascript 3 式と演算子


 

3 式と演算子

3.1  演算子

以下の種類の演算子を使用できます。

演算子説明
代入演算子右辺の値を左辺の変数に代入する
比較演算子比較して、その結果を返す
算術演算子算術演算して、その結果を返す
ビット演算子ビット演算して、その結果を返す
論理演算子論理演算して、その結果を返す
文字列演算子文字列演算して、その結果を返す
条件(三項)演算子条件値に応じて 2 つの値のいずれかを返す
コンマ演算子左から右に評価する
単項演算子演算子の右辺のみに演算子を適用する
関係演算子単純な比較ではなく関係を評価して、その結果を返す

3.1.1 代入演算子

代入演算子には、左辺に右辺の値を代入する時に使用する = 演算子があります。また、= と他の演算子と組み合わせた、演算を行ってから代入する演算子があります。

演算子説明
=右辺の値を左辺の変数に代入する
*=右辺と左辺の乗算結果を左辺の変数に代入する
/=右辺と左辺の除算結果を左辺の変数に代入する
%=右辺と左辺の剰余結果を左辺の変数に代入する
+=右辺と左辺の加算結果を左辺の変数に代入する
/=右辺と左辺の減算結果を左辺の変数に代入する
**=右辺と左辺のべき乗結果を左辺の変数に代入する
<<=左辺を右辺の値だけ左シフトした結果を左辺の変数に代入する
>>=左辺を右辺の値だけ右算術シフトした結果を左辺の変数に代入する
>>>=左辺を右辺の値だけ右論理シフトした結果を左辺の変数に代入する
&=右辺と左辺のビット論理積結果を左辺の変数に代入する
|=右辺と左辺のビット論理和結果を左辺の変数に代入する
^=右辺と左辺のビット排他的論理和結果を左辺の変数に代入する

配列内のデータを取り出して別個の変数に代入することもできます。関数の戻り値が配列の場合も同様に代入できます。

記述例
<span id="d01"></span> <span id="d02"></span> <span id="d03"></span><br>
<!-- 以下略 -->

<script>
  var [one, two, three] = [1, 2, 3];                    // one = 1; two = 2; three = 3;
  document.getElementById("d01").textContent=one;
  document.getElementById("d02").textContent=two;
  document.getElementById("d03").textContent=three;
  var [a, b] = (function() {return [1, 2];})();         // a = 1; b = 2;
  document.getElementById("d21").textContent=a;
  document.getElementById("d22").textContent=b;

</script>
実行例

関数の呼び出し、配列への代入、構造化代入に対して、...により、配列を展開して用いることができます。

代入元に記述した場合は、...の後に記述された配列の値がそこに書かれていたかのように代入されます。つまり、一つ目の例は b = [1, 2, 3, 4] と同じ意味になります。

また、代入先に記述された場合は、...の先に書かれている変数に入らなかった値がすべて ...の後に書かれた変数に配列として入ります。

記述例
<span id="d01"></span> <span id="d02"></span> <span id="d03"></span> <span id="d04"></span><br>
<!-- 以下略 -->

<script>
  var a = [3, 4];
  var b = [1, 2, ...a];       // b = [1, 2, 3, 4] と同じ
  document.getElementById("d01").textContent = b[0];
  document.getElementById("d02").textContent = b[1];
  document.getElementById("d03").textContent = b[2];
  document.getElementById("d04").textContent = b[3];

  var [first, second, ... others] = [1, 2, 3, 4];       // first = 1; second = 2; others = [3, 4];
  document.getElementById("d11").textContent = first;
  document.getElementById("d12").textContent = second;
  document.getElementById("d13").textContent = others[0];
  document.getElementById("d14").textContent = others[1];
</script>
実行例

オブジェクトでも、メンバ変数(プロパティ)と同じ名前の別個の変数に代入することができます。また、宣言済みの変数に代入する場合は代入文をかっこで囲む必要があります。

記述例
<span id="d01"></span> <span id="d02"></span> <span id="d03"></span><br>
<span id="d11"></span> <span id="d12"></span> <span id="d13"></span><br>

<script>
  var {one, two, three} = {one:1, two:2, three:3};        // one = 1; two = 2; three = 3;
  document.getElementById("d01").textContent=one;
  document.getElementById("d02").textContent=two;
  document.getElementById("d03").textContent=three;
  var x, y, z;        // 宣言済みの変数に代入する場合は、代入文をかっこで囲む
  ({x, y, z} = {x:1, y:2, z:3});        // x = 1; y = 2; z = 3;
  document.getElementById("d11").textContent=x;
  document.getElementById("d12").textContent=y;
  document.getElementById("d13").textContent=z;
</script>

オブジェクトの場合は、基本的にオブジェクトのプロパティ名と値を代入される変数名が一致している必要がありますが、次のようにすれば別名の変数に代入することもできます。

<span id="d21"></span> <span id="d22"></span> <span id="d23"></span><br>

<script>
  var {one:a, two:b, three:c} = {one:1, two:2, three:3};        // a = 1; b = 2; c = 3;
  document.getElementById("d21").textContent=a;
  document.getElementById("d22").textContent=b;
  document.getElementById("d23").textContent=c;
</script>
実行例

3.1.2 比較演算子

型変換しないで厳密に比較する方法と、型変換し抽象的に比較する方法の 2 通りがあります。厳密な比較では、オペランドが同じ型である場合に限り真になります。より一般的に使用される抽象的な比較では、比較する前にオペランドを同じ型に変換します。

演算子説明
==抽象的な比較をし、オペランド同士が等しいならば真を返す
!=抽象的な比較をし、オペランド同士が等しくないならば真を返す
===厳密な比較をし、オペランド同士が等しいならば真を返す
!==厳密な比較をし、オペランド同士が等しくないならば真を返す
>左辺が右辺より大きいならば真を返す
>=左辺が右辺より大きいか等しいならば真を返す
<左辺が右辺より小さいならば真を返す
<=左辺が右辺より小さいか等しいならば真を返す

== と != は、型変換を行った上で値を比較しますが、=== と !== は、型を変換することなく比較します。

記述例
<div id="d1"></div>
<!-- 以下略 -->

<script>
  document.getElementById("d1").textContent=(3 == 3);    // true  抽象的な比較(型変換し値を比較)
  document.getElementById("d2").textContent=(3 == '3');  // true  抽象的な比較(型変換し値を比較)

  document.getElementById("d3").textContent=(3 === 3);   // true  厳密な比較(そのまま値を比較)
  document.getElementById("d4").textContent=(3 === '3'); // false 厳密な比較(型が異なる時点で不一致)
</script>
実行例

3.1.3 算術演算子

算術演算をし、1 つの数値を返します。これらの演算子は、浮動小数点数を用いた場合と同じように計算されます。

ただし、0 で除算した結果は、Infinity あるいは -Infinity になります。

演算子使用例説明
+x + y左辺値と右辺値との和を返す
-x - y左辺値から右辺値を減算した差を返す
*x * y左辺値と右辺値との積を返す
/x / y左辺値を右辺値で除算した商を返す
%x % y左辺値を右辺値で除算したときの、整数の余りを返す
**x ** y左辺値を右辺値でべき乗した値(xy)を返す
++++x1を加算し、加算後の値を返す
x++1を加算し、加算前の値を返す
----x1を減算し、減算後の値を返す
x--1を減算し、減算前の値を返す
--x符号を反転し、その値を返す
++xそのままの値を返す
記述例
<div id="d1"></div>
<!-- 以下略 -->

<script>
  document.getElementById("d1").textContent=1 / 2;        // 0.5  実数演算
  document.getElementById("d2").textContent=1 / 0;        // Infinity  無限大
</script>
実行例

3.1.4 ビット演算子

被演算子を 32 ビットの集合(0 と 1)として扱います。

ただし、演算結果は、10 進数表現の数値を返します。

演算子使用例説明
&x & y左辺値と右辺値とのビットごとの論理積を返す
|x | y左辺値と右辺値とのビットごとの論理和を返す
^x ^ y左辺値と右辺値とのビットごとの排他的論理和を返す
~~x各ビットを反転した値を返す
<<x << y左辺値を右辺値のビット分だけ左にシフトする。右からは 0 が埋められる
>>x >> y左辺値を右辺値のビット分だけ右にシフトする。左からは最上位のビット(符号ビット)が埋められる
>>>x >>> y左辺値を右辺値のビット分だけ右にシフトする。左からは 0 が埋められる
記述例
<div id="d1"></div>
<!-- 以下略 -->

<script>
  function hex(n) {
    // 16進数文字列変換(略)
  }
  document.getElementById("d1").textContent=hex(0x12345678 & 0xFFFF0000);  // 0x12340000;
  document.getElementById("d2").textContent=hex(0x12345678 | 0xFFFF0000);  // 0xFFFF5678;
  document.getElementById("d3").textContent=hex(0xFFFF0000 ^ 0xFF00FF00);  // 0x00FFFF00;
  document.getElementById("d4").textContent=hex(~0xFFFF0000);              // 0x0000FFFF;
  document.getElementById("d5").textContent=hex(0x12345678 << 8);          // 0x34567800;
  document.getElementById("d6").textContent=hex(0x87654321 >> 8);          // 0xFF876543;  算術右シフト
  document.getElementById("d7").textContent=hex(0x87654321 >>> 8);         // 0x00876543;  論理右シフト
</script>
実行例

3.1.5 論理演算子

論理演算をし、ブール値を返します。

ただし、非ブール値を記述した場合は、非ブール値を返す可能性があります。

演算子使用例説明
&&x && y左辺値と右辺値との論理積を返す
||x || y左辺値と右辺値との論理和を返す
!!xtrue と見ることができる場合は、false を返すそうでない場合は true を返す
記述例
<div id="d1"></div>
<!-- 以下略 -->

<script>
  document.getElementById("d1").textContent=true && true;         // true
  document.getElementById("d2").textContent=true && false;        // false
  document.getElementById("d3").textContent=true || false;        // true
  document.getElementById("d4").textContent=false || false;       // false
  document.getElementById("d5").textContent=!true;                // false
  document.getElementById("d6").textContent="A" || false;         // "A"  非ブール値
</script>
実行例

3.1.6 文字列演算子

結合演算をし、2 つの文字列を結合した文字列を返します。

演算子使用例説明
+x + y左辺値と右辺値とを結合した文字列を返す
記述例
<div id="d1"></div>
<!-- 以下略 -->

<script>
  document.getElementById("d1").textContent="ABC" + "DE";         // "ABCDE"
  document.getElementById("d2").textContent="12" + 34;            // "1234"
  document.getElementById("d3").textContent="ABC" + null;        // "ABCnull"
</script>

数値との演算もできますが、あくまで文字列の結合です。加算にはなりません。

実行例

3.1.7 条件(三項)演算子

条件に基づいて 2 つの値のうち 1 つを選択します。

演算子使用例説明
? :cond ? x : y条件 cond が true の場合 x、false の場合 y を返す
記述例
<div id="d1"></div>

<script>
  var n = 10;
  var v1 = n > 9 ? "Upper" : "Lower";         // v1 = "Upper";
</script>
実行例

3.1.8 カンマ演算子

演算対象を (左から右に) 評価し、最後の値を返します。主に for 文内で使用されます。

演算子使用例説明
,x, y, z演算対象を順に評価し、最後の値を返す。主に for 文内で使用される
var sum = 0;
for (var i = 0, j = 9; i < 10; i++, j--) {
  sum += a[i][j];
}

3.1.9 単項演算子

単項演算は 1 個の被演算子だけを取る演算です。

演算子使用例説明
newnew Date()コンストラクタ関数を持ったユーザ定義のオブジェクト型または内蔵オブジェクト型のインスタンスを生成する
deletedelete xオブジェクトやオブジェクトのプロパティ、配列の指定されたインデックスの要素を削除する
var や let 文で宣言された変数は削除できない。ただし、プロパティや配列要素は削除できる
typeoftypeof x未評価の被演算子の型を指す文字列を返す
voidvoid x値を返さずに評価する式を指定する
記述例
<div id="d1"></div>
<!-- 以下略 -->

<script>
  document.getElementById("d1").textContent=typeof new Date();      // object
  document.getElementById("d2").textContent=typeof new Function();  // function
  document.getElementById("d3").textContent=typeof "";              // string
  document.getElementById("d4").textContent=typeof 0;               // number
  document.getElementById("d5").textContent=typeof zzz;             // undefined (zzz は未定義)

  x = 0;
  delete x;            // x は未定義になる
  document.getElementById("d11").textContent=typeof x;      // 単に x と記述すると例外が発生する
  var v = {a:1, b:2, c:3};
  delete v.b;          // v.b は undefined になる
  document.getElementById("d12").textContent=typeof v.b;
  var a = [1,2,3,4];
  delete a[2];         // a[2] は undefined になる
  document.getElementById("d13").textContent=typeof a[2];
</script>

存在しない変数を参照すると例外が発生します。この例では、typeof で変数の存在を確認しています。

実行例

3.1.10 関係演算子

左辺値と右辺とを演算子による比較をし、比較結果を返します。

演算子使用例説明
inx in y左辺値が右辺の添字として有効か、プロパティ(属性)にある場合に true を返す
instanceofx instanceof y左辺の値が右辺(あるいは右辺のサブクラス)のインスタンスである場合に true を返す
記述例
<div id="d1"></div>
<!-- 以下略 -->

<script>
  var a = [1,2, ,4,5];
  document.getElementById("d1").textContent=0 in a;        // true (a には 0 番目の要素がある)
  document.getElementById("d2").textContent=2 in a;        // false (a には 2 番目の要素がない)
  document.getElementById("d3").textContent="length" in a; // true (配列には length 属性がある)

  var b = {a:1, b:2, d:3};
  document.getElementById("d11").textContent="a" in b;    // true (b に a というプロパティがある)
  document.getElementById("d12").textContent="c" in b;    // false (b に c というプロパティはない)

  var d = new Date();
  document.getElementById("d21").textContent=d instanceof Date;  // true (d は Date のインスタンス)
  document.getElementById("d22").textContent=d instanceof Object;// true (d は Object のサブクラスである Date のインスタンス)
  document.getElementById("d23").textContent=d instanceof Array; // false (d は Array のインスタンスではない)
  document.getElementById("d24").textContent=a instanceof Array; // true (a は Array のインスタンス)
</script>
実行例

3.2  演算子の優先順位

演算子の優先順位は、演算子が評価される順番を決定します。より高い優先順位の演算子は最初に評価されます。

また、同じ優先順位の演算子(OP)が次のように指定されていた場合、どのような順番で評価されるかは演算子の「結合性」によります。

a OP b OP c

次のように、( ) 内から先に評価するように、左から評価することを「左結合性 (左から右)」といいます。

(a OP b) OP c

また、次のように、右から評価することを「右結合性 (右から左)」といいます。

a OP (b OP c)

以下の表は優先順位の最も高いもの (18) から最も低いもの (0) の順に並べられています。

優先順位演算子説明結合性
18( )2 * (a + 1)  (優先順位の変更)
17.object.property  (メンバーの参照)左から右
[ ]object["property"]  (メンバーの参照)左から右
newnew class(引数)  (引数を伴うインスタンスの生成)
16newnew class  (引数のないインスタンスの生成)右から左
15++、--a++、a--  (後置インクリメント、後置デクリメント)右から左
14!、~!a、~a  (論理値の否定、ビットごとの NOT)右から左
+、-+a、-a  (符号)右から左
++、--++a、--a  (前置インクリメント、前置デクリメント)右から左
typeof、void、deletetypeof a、void a、delete a  右から左
13**a ** 2  (べき乗)右から左
12*、/、%a * 1、a / 2、a % 2  (乗算、除算、剰余)左から右
11+、-a + 1、a - 2  (加算、減算)左から右
10<<、>>、>>>a << 1、a >> 2、a >>> 2  (シフト)左から右
9<、<=、>、>=a < b、a <= b、a > b、a >= b  (比較)左から右
in、instanceof1 in a、a instanceof b 左から右
8==、!=、===、!==a == b、a != b、a === b、a !== b  (比較)左から右
7&a & b  (ビットごとの AND)左から右
6^a ^ b  (ビットごとの XOR)左から右
5|a | b  (ビットごとの OR)左から右
4&&a && b  (論理値の AND)左から右
3||a || b  (論理値の OR)左から右
2? :cond ? a : b  (条件演算)右から左
1=、+=、-=、*=、/=、%=、<<=、>>=、>>>=、&=、^=、|=a = b、a += b、a -= b、a *= b、a /= b、...  (代入)右から左
0,a, b 左から右

3.3  式

JavaScript には、以下の種類の式があります。

また、あらゆる式は、文でもあります。ひとつの文が数行に渡る場合もありますし、複数の文それぞれがセミコロン(;)で区切られていれば 1 行となる場合もあります。

(1) 基本式

基本のキーワードと一般的な式です。

 this

this キーワードを使用することでカレントオブジェクトを参照できます。一般的には this は、あるメソッド内で呼び出されるオブジェクトを参照します。

次の例のようにクリックイベントなどで呼び出されたときの now() 内の this の値は、id='x' の div 要素への参照となります。

ただし、this はその記述された場所やその参照の方法などで様々な値をとりますので注意が必要です。詳しくは 「7.5 this」 を参照してください。

記述例
<div id="x">今の日時</div>
<script>
function now() {
  let t = new Date();
  this.textContent=t.toLocaleDateString() + " " + t.toLocaleTimeString();
}
document.getElementById('x').addEventListener('click', now, false);     // イベントハンドラの追加
</script>
表示例

(2) 左辺式

左辺の値が代入先になるような式です。

 new

new 演算子は、ユーザ定義オブジェクトやビルトインオブジェクトのインスタンス作成に使用します。new の使用法は以下のとおりです。

記述例
  var t = new Date();

(3) 算術式

評価結果が数値になるような式です。

記述例
  var n = a++ - 1;

(4) 文字列式

評価結果が文字列になるような式です。

記述例
  var n = "a" + 1;

(5) 論理式

評価結果が論理値になるような式です。

記述例
  var n = a > 1;