JavaScript入門 演算子
JavaScript には基本的な演算子のみ用意されており、高度な演算を行う場合は「Math」オブジェクトを利用するようになっています。JavaScript で使用できる演算子は、次の表のようになっています。ビットシフト演算は32ビット長で処理されます。ビット演算以外の計算に関してはIEEE754の規格に沿って処理されます。
演算子とオペランド
演算子とは、値をもとに何らかの処理を行い、その結果を返す記号のことです。演算子によって、処理される値を「オペランド」を呼びます。
演算子の動きについて
a = 1 + 2;
上記の実行文は、次のようなステップで実行されます
- 1 + 2の部分が処理され、結果の3が取得されます。
- a = 3の状態になるため、aに対して3が代入されます。
=より先に+の演算子が実行されるのは、演算子には優先順位があるからです。
演算子の優先順位
演算子の処理には優先順位があり、実行文の中に複数の演算子が存在する場合には、優先順位の高いものから順番に処理されていきます。
結合性
演算子の優先順位が同じ場合には、演算子の結合性によって処理する順番が決まります。結合性には、「左から右」、「右から左」に処理するものがあります。
a = b = 1;
具体的に以下の順序で処理されます
- JavaScript エンジンは、まず実行文を解析し、使われている演算子の優先順位を確認します。このとき、優先順位に差があれば、優先順位が高い演算子から処理されます
- 使われている演算子の優先順位が同じ場合は、実行文の左側の演算子から解析します。そして、最初の演算子(=)に出会うと、右側の処理を先に行うべきと判断し、最初の=演算子の実行を保留します。
- 右側にあるb=1を解析し、2番目の=演算子に出会います。2番目の演算子の右側には数値の1があります。1という式は1という処理結果を返して終わります。したがって、2番目の=演算子の右側の処理が終わったので、次に変数bに1が代入されます。
- これで最初の=演算子の右側のオペランド処理が終わり、最初の=演算子による変数aへの代入が実行されます。
結果としては、aに1が代入されます。
(数字が大きいほうが優先順位が高い)
優先順位 | 演算子の種類 | 結合性 | 記号/キーワード |
---|---|---|---|
21 | グループ化 | なし | () |
20 | メンバーへのアクセス | 左から右 | . |
計算値によるメンバーへのアクセス | 左から右 | [] | |
new(引数リスト付き) | なし | new | |
関数呼び出し | 左から右 | () | |
オプショナルチェイニング | 左から右 | ?. | |
19 | new(引数リストなし) | 右から左 | new |
18 | 後置インクリメント、後置デクリメント | なし | …++、…– |
17 | 論理NOT、ビットごとのNOT、単項+、単項-、前置インクリメント、前置デクリメント、typeof、void、delete、await | 右から左 | !、~、+、-、++…、–…、typeof、void、delete、await |
16 | べき乗 | 右から左 | ** |
15 | 乗算、除算、剰余 | 左から右 | *、/。% |
14 | 加算、減算 | 左から右 | +、- |
13 | 左ビットシフト、右ビットシフト、符号なし右ビットシフト | 左から右 | <<、>>、>>> |
12 | 小なり、小なりイコール、大なり、大なりイコール、in、instanceof | 左から右 | <、<=、>、>=、in、instanceof |
11 | 等価、不等価、厳密等価、厳密不等価 | 左から右 | ==、!=、===、!== |
10 | ビット単位AND | 左から右 | & |
9 | ビット単位XOR | 左から右 | ^ |
8 | ビット単位OR | 左から右 | | |
7 | 論理AND | 左から右 | && |
6 | 論理OR | 左から右 | || |
5 | Null合体 | 左から右 | ?? |
4 | 条件 | 右から左 | ?、: |
3 | 代入 | 右から左 | =、+=、-=、**=、*=、/=、%=、<<=、>>=、>>>=、&=、^=、|=、&&=、||=、??= |
2 | yield、yield* | 右から左 | yield、yield* |
1 | カンマ/シーケンス | 左から右 | , |
グループ化演算子
演算子の順番を意図的に変更したい場合は、グループ化演算子です。グループ化演算子は丸カッコで囲みます。演算の優先順位が21で最優先で処理されます。
console.log( 1 + 2 * 3);
結果は+より*が優先順位が高いため、2 * 3の計算をします。その後に1+6(2*3)をします。
では、1+2を最優先で計算する場合は、次のようにします
console.log( (1 + 2) * 3); // 1 + 2を()で囲みます
算術演算子
数値計算に使う演算子を算術演算子といいます。
演算子 | 意味 | 記述例 | 演算結果 (x=12 y=4) |
---|---|---|---|
+ | 加算 | z= x + y | 16 |
– | 減算 | z= x – y | 8 |
* | 乗算 | z= x * y | 48 |
/ | 除算 | z= x / y | 3 |
% | 剰余 | z= x % y | 0 |
++ | プリインクリメント | y = ++x | y=13、x=13 (代入前に加算) |
++ | ポストインクリメント | y = x++ | y=12、x=13 (代入後に加算) |
— | プリデクリメント | y = –x | y=11、x=11 (代入前に減算) |
— | ポストデクリメント | y = x– | y=12、x=11 (代入後に減算) |
インクリメント演算子とデクリメント演算子
インクリメント演算子(++)とデクリメント演算子(–)は、オペランドに変数を取ることで、変数が保持している値に+1(インクリメント)、-1(デクリメント)します。
let x = 0;
++x; //インクリメント演算子で変数xの値を+1にする
console.log( x ); //xの元の値(0)に+1した値がxに格納されるため、結果は1となる
>1
--x; //デクリメント演算子で変数xの値を-1にする
console.log( x ); //xの元の値(0)に-1した値がxに格納されるため、結果は0となる
>0
インクリメント演算子とデクリメント演算子には、前置(++xや–x)と後置(x++やx–)の2種類のパターンがあります。前置と後置では、元の変数に+1してから代入するのか、代入してから元の変数に+1するのかという挙動の違いになります。
++オペランド //前置インクリメント
オペランド++ //後置インクリメント
--オペランド //前置デクリメント
オペランド-- //後置デクリメント
前置インクリメント
let a= 0;
let b= ++a;
console.log("a:",a,"b:",b);
>a:1 b:1 //変数aと変数bは同じ値
後置インクリメント
let a= 0;
let b= a++;
console.log("a:",a,"b:",b);
>a:1 b:0 //変数bには+1する前の値が代入される
この動作は、前置デクリメントと後置デクリメントも同様です。
等価演算子
等価演算子は、値を比較する際に使う演算子で、その戻り値はBoolean型の真偽値(trueまたはfalse)になります。
厳密な透過性と抽象的な透過性
厳密な透過性
値が同じでも型が異なる場合は、結果をfalseを返します
1 === 1 //結果はtrue
1 === "1" //結果はfalse
1 === true //結果はfalse
抽象的な透過性
ここで注目は、1 === trueがtrueを返すということです、trueは値は異なりますが型変換により1となりtrueになってしまいます。その他にも「null」と「undefined」を比べたとき、trueを返します。
1 == 1 //結果はtrue
1 == "1" //結果はtrue
1 == true //結果はtrue
console.log( null == undefined );
>true
比較演算子 | 意味 | 例 | 結果 |
---|---|---|---|
== | 値が等しい | 1==”1″ 1 == 1 | true true |
=== | 値と型が等しい | 1 === “1” 1 === 1 | false true |
!= | 値が等しくない | 1 != “1” 1 != 2 | false true |
!== | 値と型が等しくない | 1 !== “1” 1 !== 1 | true false |
オブジェクトの比較
オブジェクト比較の場合は、そのオブジェクトが格納されているアドレス同士の比較を行います。変数aと変数bは、異なるオブジェクトに対して参照を保持しているため結果はfalseとなります。
const a = {};
contst b = {};
console.log( a === b );
>false
関係演算子
関係演算子は、オペランドを比較しその比較が真かどうかに基づいてboolean型の真偽値を返します。
比較演算子 | 意味 | 例 | 結果 |
---|---|---|---|
> | 左が大きい | 1 < 2 1 < 1 | true false |
>= | 左が等しいか大きい | 2 > 1 1 > 1 | true false |
< | 右が大きい | 1 <= 2 2 <= 2 | true true |
<= | 右が等しいか大きい | 2 >= 1 2 >= 2 | true true |
A in B | AのプロパティがBのオブジェクトのプロパティとして含まれるかの確認 | “val” in {val: 1} “noVal” in { val: 1} | true false |
代入演算子
代入演算子(=)は、左のオペランドに対して、右のオペランドを代入するときに使います。
代入演算子 | 記述例 | 「=」を使った記述 |
---|---|---|
= | x=y | なし |
let a = 0; //aに0が代入されます。
let b;
let c = b = 0; //一番右の値がそれぞれの変数に代入されます。※1
自己代入演算子
自己代入演算子とは、代入演算子とその他の演算子の組み合わせで、+=のような形で表現される演算子のことです。
let a = 0;
a += 1;
console.log(a);
>1
a = a + 1 //自己代入演算子を使わない場合
a += 1 //自己代入演算子を使った場合
++a //インクリメント演算子で表した場合
代入演算子 | 説明 | 例 | 結果 |
---|---|---|---|
+= | 加算の自己代入 | let a = 10; a += 2; console.log( a ); | 12 |
-= | 減算の自己代入 | let a = 10; a -= 2; console.log( a ); | 8 |
*= | 乗算の自己代入 | let a = 10; a *= 2; console.log( a ); | 20 |
/= | 除算の自己代入 | let a = 10; a /= 2; console.log( a ); | 5 |
%= | 余算の自己代入 | let a = 10; a %= 3; console.log( a ); | 1 |
**= | べき乗の自己代入 | let a = 10; a **= 2; console.log( a ); | 100 |
&&= | 論理積の自己代入 | let a = true; a &&= false; console.log( a ); | false |
||= | 論理和の自己代入 | let a = true; a ||= false; console.log( a ); | true |
??= | Null合体の自己代入 | let a = null; a ??= “初期値”; console.log( a ); | 初期値 |
論理演算子
論理演算子は、オペランドの論理積または論理和を求めたいときに使う演算子です。if文などの条件式で複数の条件を組み合わせるときに使います。
演算子 | 意味 | 記述例 | 演算結果 (x=12 y=4) |
---|---|---|---|
&& | 論理積(論理式) A && Bの場合、AかつBの条件を表す | ( x == 12 ) && ( y == 4 ) | true |
|| | 論理和(論理式) A || Bの場合、AまたはBの条件を表す | ( x == 12 ) || ( y == 4 ) | true |
論理積の場合には左右のオペランドがともにtrueのときのみにtrueを返し、それ以外の場合はfalseを返します。一方、論理和の場合は、左右のオペランドのどちらかがtrueであればtrueを返します。どちらもfalseの場合のみ、falseを返します。
falsyな値とtruthyな値
Boolean関数で値を真偽値に変換したときに、falseが返ってくる値のことを「falsy(フォルシー)」、trueが返ってくる値のことを「truthy(トゥルーシー)」と呼びます。falsyな値とは、以下の8つです。これ以外の値をBoolean関数で真偽値に変換した場合には、trueを返します。
- false
- 0
- -0
- on
- “”(空文字)
- null
- undefined
- Nan
Boolean関数で真偽値に変換
console.log( Boolean( 0 ) );
>false
console.log( Boolean( "" ) );
>false
console.log( Boolean( null ) );
>false
console.log( Boolean( undefined ) );
>false
console.log( Boolean( NaN ) );
>false
論理積(AND条件)
論理積(&&)の場合には、左から右にtruthyな値かどうか判定します。「オペランドの評価の途中でfalsyな値が見つかった場合は、その値を論理積の結果として返し、演算子としての処理を終了します」
console.log( "hello" && "world" );
>world
console.log( "hello" && underined );
>underined
console.log( null && "world" );
>null
console.log( "hello" && "world" && "!!" );
>!!
論理和(OR条件)
論理和(||)の場合も、左から右にtruthyかどうか判定します。論理積と異なるのは、論理和の場合、truthyな値が見つかった時点で、その値を論理和の結果として返し、演算子としての処理を終了する点です。また、論理積と同様に最後のオペランドまで到達すると、truthyかfalsyか関係なく、そのオペランドを返します。
console.log( "hello" || "world" );
>hello
console.log( "hello" || underined );
>hello
console.log( null || "world" );
>world
console.log( null || undefined );
>undefined
console.log( null || "" || undefined );
>undefined
その他の演算子
カンマ演算子
カンマ演算子(,)はそれぞれの演算対象を左から右に評価し、最後のオペランドの値を返します。
カンマ演算子の記法
式1,式2・・・
let a = 0, b = 1;
console.log( a , b );
> 0 1
単項演算子
単項演算子は、オペランドが1つの演算子です。delete演算子やtypeof演算子などです。
演算子 | 用途 | 例 | 結果 |
---|---|---|---|
delete | オブジェクトから特定のプロパティを削除 | const obj = { val: 1 }; delete obj.val; | obj:{} |
typeof | データ型の確認 | typeof 1 typeof “hello” | nuimber string |
! | 真偽値に変換して、反対の真偽値を取得 | !true !false !!true !”hello” ( truthy→false ) !”” (falsy→true) | false true true false true |
+ | Number型への変換 | +”10″ +true +false | 10 1 0 |
– | Number型へ変換して、正負を入れ替え | -“1” -“2” | -1 -2 |
三項演算子
三項演算子は、条件が真のとき、偽りのときに実行する式を切り替えることができる演算子です。三項演算子は、「?」と「:」(コロン)で区切って指定します。
構文
条件式 ? { 条件式がtruthyのときに実行 } : { 条件式がfalsyのときに実行 }
条件を満たした場合には「?」直後の値が代入され、条件を満たしていない場合には「:」より後ろの値が代入されます。
( 1 === 1 ) ? console.log( "真" ) : console.log( "偽" );
>真
( 1 === 2 ) ? console.log( "真" ) : console.log( "偽" );
>偽
ES6以降の演算子
対応しているどうかは以下のサイトで確認ができます。
Can I use(https://caniuse.com/)
Null合体演算子
Null合体演算子(??)は、変数に初期値を設定するときに使われる演算子です。左のオペランドがnullまたはundefinedの場合は、右のオペランドを返します。それ以外の場合は、左のオペランドを返します。nullもしくはundefinedが変数に設定されている場合に、数値や文字列などの有効な値が変数に格納されていないときに、Null合体演算子で値を設定します。使いどころとしては、プログラムのどこかでnullが設定されている場合などに初期値を設定するなどに使用されます。
Null合体演算子の使い方
let val = null;
//右辺のvalはnullのため初期値がvalが設定される
val = val ?? "初期値";
console.log( `val [ ${ val } ]` );
>val [ 初期値 ]
// null、undefined以外は左のオペランドを返します。
let num = 0;
num = num ?? 10;
console.log( `num [ ${ num } ]` );
>num [ 0 ]
論理和(||)を使った場合
論理和を使った場合は、nullやundefined以外のfalsyな値、数値の0や””(空文字)にも初期値が設定されます。
//""はfalsyな値
let val = "";
val = val || "初期値";
console.log( `val [ ${ val } ]` );
>val [ 初期値 ]
オプショナルチェイニング演算子
オプショナルチェイニング演算子(?.)は、オブジェクト以外の値に対してプロパティを取得した時にundefinedを返す演算子です。通常、オブジェクトのプロパティの値を取得する際にはドット演算子(.)を使いますが、ドット演算子では左オペランドがオブジェクトでない場合にエラーが発生します。
const val = undefined.prop; //undefinedはオブジェクトではないためエラーが発生
> Uncaught TypeError: Cannot read property "prop" of undefined
一方、オプショナルチェイニング演算子を使った場合には、エラーは発生せずundefinedが返されます。
const val = undefined?.prop;
console.log( val );
> undefined
オプショナルチェイニング演算子は、オブジェクトのプロパティとして存在するかどうか不明瞭なときに使用するのが有効的です。
オプショナルチェイニング演算子をメソッドやブラケット記法と組み合わせ使う場合
//メソッドに使う場合は末尾の丸括弧の前に記述
undefined.notMethod?.();
//ブラケット記法と併用可能
undefined?.[ "prop" ];
//他のプリミティブ型に対しても可能
1?.prop;