BETA

今更ながらJavaScriptを1から勉強してみる【その4】

投稿日:2019-06-04
最終更新:2019-06-04

この記事は以下の続きとなります。

今更ながらJavaScriptを1から勉強してみる【その3】

演算子

足し算引き算の+-など、よくある演算を記号で表現したもの。
演算子の対象のことを被演算子(オペランド)という。以下のコードでは+が演算子で、1と2がオペランド。
オペランドを2つ取るものを二項演算子、1つ取るものを単項演算子と呼ぶ。

// +は二項演算子で、1と2にがオペランド  
1 + 2;  

// ++は単項演算子でnumがオペランド  
nul++;  

二項演算子

プラス演算子(+)

2つの数値を加算する演算子です。
JavaScriptは数値は内部で浮動小数点数として表現されているため、整数と浮動小数点数の加算もできます。

console.log(1 + 1); // => 2  
console.log(10 + 0.5); // => 10.5  

マイナス演算子(-)

2つの数値を原産する演算子です。

console.log(1 - 1); // => 0  
console.log(10 - 0.5); // => 9.5  

乗算演算子(*)

2つの数値を乗算する演算子です。

console.log(2 * 8); // => 16  
console.log(10 * 0.5); // => 5  

除算演算子(/)

2つの数値を除算する演算子です。
結果は商だけが出力されて、あまりは出力されません。

console.log(8 / 2); // => 4  
console.log(10 / 0.5); // => 20  

乗除演算子(%)

2つの数値を除算したあまりを求める演算子です。

console.log(8 % 2); // => 0  
console.log(9 % 2); // => 1  
console.log(10 % 0.5); // => 0  
console.log(10 % 4.5); // => 1  

[ES2016]べき乗演算子(**)

2つの数値のべき乗を求める演算子です。
左オペランドを右オペランドでべき乗した値を返します。

// べき乗演算子(ES2016)で2の4乗を計算  
console.log(2 ** 4); // => 16  

なおべき乗演算子と同様の動作をするMath.powメソッドがあります。

console.log(Math.pow(2, 4); // => 16  

べき乗演算子はES2016から追加された演算子のため関数と演算子が存在しているが、他の二項演算子は演算子が先に存在していたため、対応するMathのメソッドは存在していません。

単項演算子

単項演算子は1つのオペランドを受け取り実行する演算子です。

単項プラス演算子(+)

単項演算子の+はオペランドを数値に変換します。

// 数値の1を数値に変換しているため、使うことはほぼない。  
console.log(+1); // => 1  

// 文字列の"1"を数値の1に変換している  
console.log(+"1"); // => 1  

数値に変換できない文字列などはNaNという特殊な値に変換されます。
NaNは"Not-a-Number"の略称で、数値ではないがNumber型を表しています。
NaNはどの値(NaN自身)とも一致しない特性を持っていて、Number.isNaNメソッドによってNaNの判定ができます。

// 数値ではない文字列はNaNに変換される  
console.log(+"文字列"); // => NaN  
// 自分自身とも一致しない  
console.log(NaN === NaN); // => false  
// Number型  
console.log(typeof NaN); // => "number"  
// Number.isNaNでNaNかどうかを判定  
console.log(Number.isNaN(NaN)); // => true  

しかし文字列から数値に変換する場合、Numberコンストラクタ関数やparseInt関数など明示的に方法が存在するため、単項プラス演算子を使うべきではありません。

単項マイナス演算子(-)

単項マイナス演算子はマイナスの数値を記述する場合に利用します。
マイナス1を -1 とかけるのは、単項マイナス演算子を利用しているからです。
また、マイナスの数値を反転することもできるほか、単項プラス演算子と同じように文字列を数値に変換できます。そして数値へ変換できない文字列をオペランドに指定した場合は、NaNになります。

// マイナス1を表記  
console.log(-1); // => -1  
// マイナスを反転してプラスの数値に  
console.log(1(-1)); // => 1  
// 文字列を数値に  
console.log(-"1"); // => -1  
// 変換できないとNaNに  
console.log(-"文字列"); // => NaN  

インクリメント演算子(++)

インクリメント演算子はオペランドの数値を+1する演算子です。

let num = 1;  
num++;  
console.log(num); // => 2  

オペランドの前後のどちらに置くかによって評価の順番が異なります。
後置インクリメント演算子(num++)は、numの評価結果を返してからnumに対して+1をします。
前置インクリメント演算子(++num)は、numに対して+1をしてからnumの評価結果を返します。

// 後置インクリメント演算子  
let x = 1;  
console.log(x++); // => 1  
console.log(x);   // => 2  

// 前置インクリメント演算子  
let y = 1;  
console.log(++y); // => 2  
console.log(y);   // => 2  

デリメント演算子(--)

デクリメント演算子はオペランドの数値を-1する演算子です。

let num = 1;  
num--;  
console.log(num); // => 0  

デクリメント演算子もインクリメント演算子と同様に、オペランドのどちらに置くかによって評価の順番が変わります。

// 後置デクリメント演算子  
let num = 1;  
console.log(x--); // => 1  
console.log(x);   // => 0  

// 前置デクリメント演算子  
let num = 1;  
console.log(--y); // => 0  
console.log(y);   // => 0  

比較演算子

比較演算子はオペランド同士の値を比較して真偽値を返す演算子です。

厳密等価演算子(===)

厳密等価演算子は、左右の2つのオペランドを比較し、同じ型で同じ値である場合にtrueを返します。

console.log(1 === 1); //   => true  
console.log(1 === "1"); // => false  

また、オペランドがどちらも同じオブジェクトの場合、オブジェクトの参照が同じ場合にtrueを返します。

// 別の参照のオブジェクトを作成  
const objA = {};  
const objB = {};  
const objC = objA;  
// 参照先が異なるためfalse  
console.log(  
// 参照先が同じなためtrue  

厳密不等価演算子(!==)

左右の2つのオペランドを比較し、異なる型または異なる値の場合にtrueを返します。
厳密等価演算子(===)を反転した結果を返す演算子です。

console.log(1 !== 1);   // => false  
console.log(1 !== "1"); // => true  

等価演算子(==)

左右の2つのオペランドを比較し、同じデータ型のオペランドを比較する場合は厳密等価演算子と同じ結果を返します。

console.log(1 == 1); // => true  
console.log("str" == "str"); // => true  
console.log("JavaScript" == "ECMAScript"); // => false  
// オブジェクトは参照が一致しているならtrueを返す  
// {} は新しいオブジェクトを作成している  
const objA = {};  
const objB = {};  
console.log(objA == objB); // => false  
console.log(objA == objA); // => true  

しかし等価演算子(==)はデータ型が違っていた場合に、同じ型となるように暗黙的な方変換をしてから比較します。
そのため意図しない挙動をすることがあるため、等価演算子(==)ではなく厳密等価演算子(===)を使うことを推奨します。

// 文字列を数値に変換してから比較  
console.log(1 == "1"); // => true  
// "01"を数値にすると`1`となる  
console.log(1 == "01"); // => true  
// 真偽値を数値に変換してから比較  
console.log(0 == false); // => true  
// nullの比較はfalseを返す  
console.log(0 == null); // => false  
// nullとundefeinedの比較は常にtrueを返す  
console.log(null == undefined); // => true  

ただし例外的にnullまたはundefinedであることを判定したい場合に使われることがあります。

const value = undefined; /* または null */  
// === では2つの値と比較する必要がある  
if (value === null || value === undefined) {  
    console.log("valueがnullまたはundefinedである場合の処理");  
}  
// == では null と比較するだけでよい  
if (value == null) {  
    console.log("valueがnullまたはundefinedである場合の処理");  
}  

不等価演算子(!=)

左右の2つのオペランドを比較し、等しくないならtrueを返します。
等価演算子(==)を反転した結果を返す演算子です。
不等価演算子も等価演算子(==)と同様に異なる型のオペランドを比較する際には、暗黙的な方変換をしてから比較するので推奨しません。

console.log(1 != 1); // => false  
console.log("str" != "str"); // => false  
console.log("JavaScript" != "ECMAScript"); // => true  
console.log(true != true);// => false  
// オブジェクトは参照が一致していないならtrueを返す  
const objA = {};  
const objB = {};  
console.log(objA != objB); // => true  
console.log(objA != objA); // => false  

大きな演算子/より大きい(>)

左オペランドが右オペランドより大きいときにtrueを返します。

console.log(42 > 21); // => true  
console.log(42 > 42); // => false  

大なりイコール演算子/以上(>=)

左オペランドが右オペランドより大きいまたは等しいときにtrueを返します。

console.log(21 <= 42); // => true  
console.log(42 <= 42); // => true  
console.log(43 <= 42); // => false  

小なり演算子/より小さい(<)

左オペランドが右オペランドより小さいときにtrueを返します。

console.log(21 < 42); // => true  
console.log(42 < 42); // => false  

小なりイコール演算子/以下(<=)

左オペランドが右オペランドより小さいまたは等しいときにtrueを返します。

console.log(21 <= 42); // => true  
console.log(42 <= 42); // => true  
console.log(43 <= 42); // => false  

ビット演算子

すみません、ビット演算はうまくまとめられなかったので、別の機会に別記事としていつかまとめたいと思います。
以下は元記事に載っているビット演算子です。

  • ビット論理積(&)
  • ビット論理和(|)
  • ビット排他的論理和(^)
  • ビット否定(~)
  • 左シフト演算子(<<)
  • 右シフト演算子(>>)
  • ゼロ埋め右シフト演算子(>>>)

代入演算子(=)

変数に対して値を代入します。
また、代入演算子は2項演算子と組み合わせることもできます。
+=、-=、*=、/=、%=、<<=、>>=、>>>=、&=、^=、|=
のように、演算した結果を代入できます。

// 通常の代入  
let x = 1;  
x = 42;  
console.log(x); // => 42  

// 2項演算子と組み合わせた代入  
let num = 1;  
num += 10; // num = num + 10; と同じ  
console.log(num); // => 11  

[ES2015]分割代入(Destructuring assignment)

ES2015から導入された構文で、配列やオブジェクトの値を複数の変数に同時に代入できます。

const array = [1, 2];  
// aには`array`の0番目の値、bには1番目の値が代入される  
const [a, b] = array;  
console.log(a); // => 1  
console.log(b); // => 2  

// 以下のように書いたのと同じ  
const array = [1, 2];  
const a = array[0];  
const b = array[1];  

配列と同様にオブジェクトも分割代入に対応しています。
右辺のオブジェクトのプロパティ値を左辺に対応するプロパティ名に代入思案す。

const object = {  
    "key": "value"  
};  
// プロパティ名`key`の値を、変数`key`として定義する  
const { key } = object;  
console.log(key); // => "value"  

// これは、次のように書いたのと同じ結果になります。  
const object = {  
    "key": "value"  
};  
const key = object.key;  

条件(三項)演算子(?と:)

条件式 ? Trueの時処理する式 : Falseの時処理する式;
条件(三項)演算子は、条件式がtrueならTrueのときする式の評価結果を、falseのときはFlaseのとき処理する式の評価結果を返します。
if分と違って条件演算子は式としてかけるので、値が返ってきます。

const valueA = true ? "A" : "B";  
console.log(valueA); // => "A"  
const valueB = false ? "A" : "B";  
console.log(valueB); // => "B"  

条件によって変数の初期値を変える場合に使われます。
次の例は、第二引数(prefix)が文字列ならその値を、それ以外(省略されたり文字列)だった場合に"デフォルト:"preに代入しています。

function addPrefix(text, prefix) {  
    // `prefix`が指定されていない場合は"デフォルト:"を付ける  
    const pre = typeof prefix === "string" ? prefix : "デフォルト:";  
    return pre + text;  
}  

console.log(addPrefix("文字列")); // => "デフォルト:文字列"  
console.log(addPrefix("文字列", "カスタム")); // => "カスタム文字列"  

論理演算子

論理演算子は真偽値を扱う演算子で、AND、OR、NOTを表現できます。

AND演算子(&&)

左辺の評価結果がtrueだった場合に右辺の評価結果を返します。
左辺の評価がtrueでなかった場合、右辺は評価されません。
値が決まった時点でそれ以上評価しないことを短絡評価(ショートサーキット)と呼びます。

const x = true;  
const y = false;  
// x -> y の順に評価される  
console.log(x && y); // => false  
// 左辺がfalseであるなら、その時点でfalseを返す  
// xは評価されない  
console.log(y && x); // => false  

OR演算子(||)

左辺の評価結果がfalseだった場合に右辺の評価結果を返します。
左辺の評価がtrueだった場合、右辺は評価されません。

const x = true;  
const y = false;  
// xがtrueなのでyは評価されない  
console.log(x || y); // => true  
// yはfalseなのでxを評価した結果を返す  
console.log(y || x); // => true  

NOT演算子(!)

オペランドの評価がtrueのときにfalseを返します。

console.log(!false); // => true  
console.log(!true);  // => false  

グループ演算子((と))

複数の2項演算子が組み合わさったときに、優先順序を明示できる演算子です。

const a = 1;  
const b = 2;  
const c = 3;  
// 加算よりも乗算が優先される  
console.log(a + b * c); // 7  
// ()で囲った加算が優先される  
console.log((a + b) * c); // => 9  

演算子の優先順位はECMAScriptで定期がされています。
グループ演算子の優先順位はもっとも高いため、優先順位を明示することができます。
演算子が複数出てくるときは明示的に優先順位を記述することで可読性をあげることができます。

if (a || b && c) {  
    // a が true または  
    // b かつ c が true  
}  
ひとつの式に複数の種類の演算子が出てくると読みにくくなる傾向があります。 このような場合にはグループ演算子を使い、結合順を明示して書くようにしましょう。  

if (a || (b && c)) {  
    // a が true または  
    // b かつ c が true  
}  

文字列結合演算子(+)

+は数値の場合は加算となりますが、オペランドが文字列の時には文字列同士の結合に利用できます。

const value = "文字列" + "結合";  
console.log(value); // => "文字列結合"  

カンマ演算子(,)

カンマ(,)で区切った式を左から順に評価し、最後の式の評価結果を返します。
一般的に利用する機会はほとんどないので、左から順に評価されるということを覚えておけば問題ありません。

const a = 1, b = 2, c = a + b;  
console.log(c); // => 3  

本日は以上となります。
演算子長かった...

技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
駆け出しエンジニアからエキスパートまで全ての方々のアウトプットを歓迎しております!
or 外部アカウントで 登録 / ログイン する
クランチについてもっと詳しく

この記事が掲載されているブログ

JavaScript / Python / React / Django / firebaseなど、自分の興味あるものを調べてアウトプットしていきたいです。

よく一緒に読まれる記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう
目次をみる
技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
or 外部アカウントではじめる
10秒で技術ブログが作れます!